├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── lint.yml │ └── tests.yml ├── .gitignore ├── CITATION.cff ├── LICENSE ├── README.md ├── configs ├── SLAC_ansible.ini ├── SLAC_chef.ini ├── SLIC_puppet.ini ├── design_ansible.ini ├── design_chef.ini ├── design_puppet.ini └── improved.ini ├── glitch ├── .gitignore ├── __init__.py ├── __main__.py ├── analysis │ ├── __init__.py │ ├── design │ │ ├── __init__.py │ │ ├── duplicate_block.py │ │ ├── imperative_abstraction.py │ │ ├── improper_alignment.py │ │ ├── long_resource.py │ │ ├── long_statement.py │ │ ├── misplaced_attribute.py │ │ ├── multifaceted_abstraction.py │ │ ├── smell_checker.py │ │ ├── too_many_variables.py │ │ ├── unguarded_variable.py │ │ └── visitor.py │ ├── rules.py │ ├── security.py │ └── terraform │ │ ├── __init__.py │ │ ├── access_control.py │ │ ├── attached_resource.py │ │ ├── authentication.py │ │ ├── dns_policy.py │ │ ├── firewall_misconfig.py │ │ ├── http_without_tls.py │ │ ├── integrity_policy.py │ │ ├── key_management.py │ │ ├── logging.py │ │ ├── missing_encryption.py │ │ ├── naming.py │ │ ├── network_policy.py │ │ ├── permission_iam_policies.py │ │ ├── public_ip.py │ │ ├── replication.py │ │ ├── sensitive_iam_action.py │ │ ├── smell_checker.py │ │ ├── ssl_tls_policy.py │ │ ├── threats_detection.py │ │ ├── versioning.py │ │ └── weak_password_key_policy.py ├── configs │ ├── default.ini │ └── terraform.ini ├── exceptions.py ├── files │ ├── obsolete_commands │ └── official_docker_images ├── helpers.py ├── parsers │ ├── .gitignore │ ├── __init__.py │ ├── ansible.py │ ├── chef.py │ ├── docker.py │ ├── gha.py │ ├── parser.py │ ├── puppet.py │ ├── resources │ │ ├── comments.rb.template │ │ └── github_workflow.json │ ├── ripper_parser.py │ ├── terraform.py │ └── yaml.py ├── repair │ ├── __init__.py │ └── interactive │ │ ├── __init__.py │ │ ├── compiler │ │ ├── compiler.py │ │ ├── labeler.py │ │ └── names_database.py │ │ ├── delta_p.py │ │ ├── filesystem.py │ │ ├── solver.py │ │ ├── tracer │ │ ├── .gitignore │ │ ├── model.py │ │ ├── parser.py │ │ ├── tracer.py │ │ └── transform.py │ │ └── values.py ├── repr │ ├── __init__.py │ └── inter.py ├── stats │ ├── print.py │ └── stats.py ├── tech.py └── tests │ ├── __init__.py │ ├── cli │ ├── resources │ │ └── chef_project │ │ │ └── test.rb │ └── test_cli.py │ ├── design │ ├── __init__.py │ ├── ansible │ │ ├── __init__.py │ │ ├── design_ansible.ini │ │ ├── files │ │ │ ├── avoid_comments.yml │ │ │ ├── duplicate_block.yml │ │ │ ├── improper_alignment.yml │ │ │ ├── long_resource.yml │ │ │ ├── long_statement.yml │ │ │ ├── multifaceted_abstraction.yml │ │ │ └── too_many_variables.yml │ │ └── test_design.py │ ├── chef │ │ ├── __init__.py │ │ ├── design_chef.ini │ │ ├── files │ │ │ ├── avoid_comments.rb │ │ │ ├── duplicate_block.rb │ │ │ ├── improper_alignment.rb │ │ │ ├── long_resource.rb │ │ │ ├── long_statement.rb │ │ │ ├── misplaced_attribute.rb │ │ │ ├── multifaceted_abstraction.rb │ │ │ └── too_many_variables.rb │ │ └── test_design.py │ ├── docker │ │ ├── __init__.py │ │ ├── files │ │ │ ├── avoid_comments.Dockerfile │ │ │ ├── duplicate_block.Dockerfile │ │ │ ├── improper_alignment.Dockerfile │ │ │ ├── long_statement.Dockerfile │ │ │ └── too_many_variables.Dockerfile │ │ └── test_design.py │ ├── gha │ │ ├── files │ │ │ └── too_many_variables.yml │ │ └── test_design.py │ ├── puppet │ │ ├── __init__.py │ │ ├── design_puppet.ini │ │ ├── files │ │ │ ├── avoid_comments.pp │ │ │ ├── duplicate_block.pp │ │ │ ├── improper_alignment.pp │ │ │ ├── long_resource.pp │ │ │ ├── long_statement.pp │ │ │ ├── misplaced_attribute.pp │ │ │ ├── multifaceted_abstraction.pp │ │ │ ├── too_many_variables.pp │ │ │ └── unguarded_variable.pp │ │ └── test_design.py │ └── terraform │ │ ├── __init__.py │ │ ├── files │ │ ├── avoid_comments.tf │ │ ├── duplicate_block.tf │ │ ├── improper_alignment.tf │ │ ├── long_statement.tf │ │ └── too_many_variables.tf │ │ └── test_design.py │ ├── hierarchical │ ├── __init__.py │ ├── ansible │ │ ├── attributes.yml │ │ └── vars.yml │ ├── chef │ │ └── vars.rb │ ├── puppet │ │ └── vars.pp │ └── test_parsers.py │ ├── parser │ ├── __init__.py │ ├── gha │ │ ├── files │ │ │ ├── index_out_of_range.yml │ │ │ ├── valid_workflow.yml │ │ │ └── valid_workflow_2.yml │ │ └── test_parser.py │ ├── puppet │ │ ├── __init__.py │ │ ├── files │ │ │ └── if.pp │ │ └── test_parser.py │ └── terraform │ │ ├── __init__.py │ │ ├── files │ │ ├── boolean_value_assign.tf │ │ ├── comments.tf │ │ ├── dict_value_assign.tf │ │ ├── dynamic_block.tf │ │ ├── empty_string_assign.tf │ │ ├── list_value_assign.tf │ │ ├── multiline_string_assign.tf │ │ ├── null_value_assign.tf │ │ └── value_has_variable.tf │ │ └── test_parser.py │ ├── repair │ └── interactive │ │ ├── delta_p │ │ └── delta_p_puppet_scripts.py │ │ ├── test_delta_p.py │ │ ├── test_delta_p_minimize.py │ │ ├── test_patch_solver.py │ │ ├── test_tracer_model.py │ │ ├── test_tracer_parser.py │ │ └── test_tracer_transform.py │ └── security │ ├── __init__.py │ ├── ansible │ ├── __init__.py │ ├── files │ │ ├── admin.yml │ │ ├── empty.yml │ │ ├── full_permission.yml │ │ ├── hard_secr.yml │ │ ├── http.yml │ │ ├── int_check.yml │ │ ├── inv_bind.yml │ │ ├── obs_command.yml │ │ ├── susp.yml │ │ └── weak_crypt.yml │ └── test_security.py │ ├── chef │ ├── __init__.py │ ├── files │ │ ├── admin.rb │ │ ├── empty.rb │ │ ├── full_permission.rb │ │ ├── hard_secr.rb │ │ ├── http.rb │ │ ├── int_check.rb │ │ ├── inv_bind.rb │ │ ├── missing_default.rb │ │ ├── obs_command.rb │ │ ├── susp.rb │ │ └── weak_crypt.rb │ └── test_security.py │ ├── docker │ ├── __init__.py │ ├── files │ │ ├── admin.Dockerfile │ │ ├── empty.Dockerfile │ │ ├── full_permission.Dockerfile │ │ ├── hard_secr.Dockerfile │ │ ├── http.Dockerfile │ │ ├── int_check.Dockerfile │ │ ├── inv_bind.Dockerfile │ │ ├── non_off_image.Dockerfile │ │ ├── obs_command.Dockerfile │ │ ├── susp.Dockerfile │ │ └── weak_crypt.Dockerfile │ └── test_security.py │ ├── puppet │ ├── __init__.py │ ├── files │ │ ├── admin.pp │ │ ├── empty.pp │ │ ├── full_permission.pp │ │ ├── hard_secr.pp │ │ ├── http.pp │ │ ├── int_check.pp │ │ ├── inv_bind.pp │ │ ├── missing_default.pp │ │ ├── obs_command.pp │ │ ├── susp.pp │ │ └── weak_crypt.pp │ └── test_security.py │ └── terraform │ ├── __init__.py │ ├── files │ ├── admin.tf │ ├── attached-resource │ │ └── aws_route53_attached_resource.tf │ ├── disabled-authentication │ │ ├── azure-app-service-authentication-activated.tf │ │ ├── contained-database-disabled.tf │ │ ├── disable-password-authentication.tf │ │ ├── gke-basic-auth.tf │ │ └── iam-group-with-mfa.tf │ ├── empty.tf │ ├── firewall-misconfiguration │ │ ├── alb-drop-invalid-headers.tf │ │ ├── alb-exposed-to-internet.tf │ │ ├── azure-keyvault-specify-network-acl.tf │ │ ├── cloudfront-use-waf.tf │ │ ├── config-master-authorized-networks.tf │ │ ├── google-compute-inbound-rule-traffic.tf │ │ ├── google-compute-no-ip-forward.tf │ │ ├── google-compute-outbound-rule-traffic.tf │ │ └── openstack-compute-no-public-access.tf │ ├── hard-coded-secrets │ │ ├── encryption-key-in-plaintext.tf │ │ ├── plaintext-password.tf │ │ ├── plaintext-value-github-actions.tf │ │ ├── sensitive-credentials-in-vm-custom-data.tf │ │ ├── sensitive-data-in-plaintext.tf │ │ ├── sensitive-data-stored-in-user-data.tf │ │ ├── sensitive-environment-variables.tf │ │ └── user-data-contains-sensitive-aws-keys.tf │ ├── hard_secr.tf │ ├── http.tf │ ├── insecure-access-control │ │ ├── access-to-bigquery-dataset.tf │ │ ├── aks-ip-ranges-enabled.tf │ │ ├── associated-access-block-to-s3-bucket.tf │ │ ├── aws-database-instance-publicly-accessible.tf │ │ ├── aws-sqs-no-wildcards-in-policy.tf │ │ ├── azure-authorization-wildcard-action.tf │ │ ├── azure-container-use-rbac-permissions.tf │ │ ├── azure-database-not-publicly-accessible.tf │ │ ├── bucket-public-read-acl.tf │ │ ├── cidr-range-public-access-eks-cluster.tf │ │ ├── cross-db-ownership-chaining.tf │ │ ├── data-factory-public-access.tf │ │ ├── google-compute-no-default-service-account.tf │ │ ├── google-gke-use-rbac-permissions.tf │ │ ├── google-storage-enable-ubla.tf │ │ ├── google-storage-no-public-access.tf │ │ ├── mq-broker-publicly-exposed.tf │ │ ├── prevent-client-disable-encryption.tf │ │ ├── private-cluster-nodes.tf │ │ ├── public-access-eks-cluster.tf │ │ ├── public-access-policy.tf │ │ ├── public-github-repo.tf │ │ ├── s3-access-through-acl.tf │ │ ├── s3-block-public-acl.tf │ │ ├── s3-block-public-policy.tf │ │ ├── s3-ignore-public-acl.tf │ │ ├── s3-restrict-public-bucket.tf │ │ ├── specify-source-lambda-permission.tf │ │ ├── storage-containers-public-access.tf │ │ └── unauthorized-access-api-gateway-methods.tf │ ├── integrity-policy │ │ ├── aws-ecr-immutable-repo.tf │ │ ├── google-compute-enable-integrity-monitoring.tf │ │ └── google-compute-enable-virtual-tpm.tf │ ├── inv_bind.tf │ ├── invalid-ip-binding │ │ ├── aws-ec2-vpc-no-public-egress-sgr.tf │ │ ├── aws-ec2-vpc-no-public-ingress-acl.tf │ │ ├── aws-ec2-vpc-no-public-ingress-sgr.tf │ │ ├── azure-network-no-public-egress.tf │ │ ├── azure-network-no-public-ingress.tf │ │ ├── cloud-sql-database-publicly-exposed.tf │ │ ├── compute-firewall-inbound-rule-public-ip.tf │ │ ├── compute-firewall-outbound-rule-public-ip.tf │ │ ├── eks-cluster-open-cidr-range.tf │ │ ├── gke-control-plane-publicly-accessible.tf │ │ ├── openstack-networking-no-public-egress.tf │ │ ├── openstack-networking-no-public-ingress.tf │ │ ├── public-egress-network-policy.tf │ │ └── public-ingress-network-policy.tf │ ├── key-management │ │ ├── aws-cloudtrail-encryption-use-cmk.tf │ │ ├── aws-cloudwatch-log-group-customer-key.tf │ │ ├── aws-documentdb-use-cmk.tf │ │ ├── aws-dynamodb-table-use-cmk.tf │ │ ├── aws-ebs-use-cmk.tf │ │ ├── aws-ecr-use-cmk.tf │ │ ├── aws-kinesis-stream-use-cmk.tf │ │ ├── aws-kms-auto-rotate-keys.tf │ │ ├── aws-neptune-use-cmk.tf │ │ ├── aws-sns-topic-encryption-use-cmk.tf │ │ ├── aws-sqs-queue-encryption-use-cmk.tf │ │ ├── aws-ssm-secret-use-cmk.tf │ │ ├── azure-storage-account-use-cmk.tf │ │ ├── digitalocean-compute-use-ssh-keys.tf │ │ ├── google-compute-disk-encryption-use-cmk.tf │ │ ├── google-compute-no-project-wide-ssh-keys.tf │ │ ├── google-compute-vm-disk-encryption-use-cmk.tf │ │ ├── google-kms-rotate-kms-keys.tf │ │ ├── google-storage-bucket-encryption-customer-key.tf │ │ ├── rds-cluster-use-cmk.tf │ │ ├── rds-instance-use-cmk.tf │ │ ├── rds-performance-insights-use-cmk.tf │ │ ├── redshift-cluster-use-cmk.tf │ │ └── s3-encryption-customer-key.tf │ ├── logging │ │ ├── aws-api-gateway-enable-access-logging.tf │ │ ├── aws-api-gateway-enable-tracing.tf │ │ ├── aws-cloudfront-enable-logging.tf │ │ ├── aws-cloudtrail-enable-log-validation.tf │ │ ├── aws-cloudtrail-ensure-cloudwatch-integration.tf │ │ ├── aws-documentdb-enable-log-export.tf │ │ ├── aws-ecs-enable-container-insight.tf │ │ ├── aws-eks-enable-control-plane-logging.tf │ │ ├── aws-elastic-search-enable-domain-logging.tf │ │ ├── aws-lambda-enable-tracing.tf │ │ ├── aws-mq-enable-audit-logging.tf │ │ ├── aws-mq-enable-general-logging.tf │ │ ├── aws-msk-enable-logging.tf │ │ ├── aws-neptune-enable-log-export.tf │ │ ├── aws-rds-enable-performance-insights.tf │ │ ├── aws-s3-enable-bucket-logging.tf │ │ ├── aws-vpc-flow-logs-enabled.tf │ │ ├── azure-container-aks-logging-configured.tf │ │ ├── azure-monitor-activity-log-retention-set.tf │ │ ├── azure-monitor-capture-all-activities.tf │ │ ├── azure-mssql-database-enable-audit.tf │ │ ├── azure-mssql-server-and-database-retention-period-set.tf │ │ ├── azure-mssql-server-enable-audit.tf │ │ ├── azure-network-retention-policy-set.tf │ │ ├── azure-postgres-configuration-enabled-logs.tf │ │ ├── azure-storage-queue-services-logging-enabled.tf │ │ ├── ensure-cloudwatch-log-group-specifies-retention-days.tf │ │ ├── google-compute-enable-vpc-flow-logs.tf │ │ ├── google-gke-enable-stackdriver-logging.tf │ │ ├── google-gke-enable-stackdriver-monitoring.tf │ │ ├── google-sql-database-log-flags.tf │ │ └── storage-logging-enabled-for-blob-service-for-read-requests.tf │ ├── missing-encryption │ │ ├── athena-enable-at-rest-encryption.tf │ │ ├── aws-codebuild-enable-encryption.tf │ │ ├── aws-ecr-encrypted.tf │ │ ├── aws-neptune-at-rest-encryption.tf │ │ ├── documentdb-storage-encryption.tf │ │ ├── dynamodb-rest-encryption.tf │ │ ├── ecs-task-definitions-in-transit-encryption.tf │ │ ├── efs-encryption.tf │ │ ├── eks-encryption-secrets-enabled.tf │ │ ├── elasticache-enable-at-rest-encryption.tf │ │ ├── elasticache-enable-in-transit-encryption.tf │ │ ├── elasticsearch-domain-encrypted.tf │ │ ├── elasticsearch-in-transit-encryption.tf │ │ ├── emr-enable-at-rest-encryption.tf │ │ ├── emr-enable-in-transit-encryption.tf │ │ ├── emr-enable-local-disk-encryption.tf │ │ ├── emr-s3encryption-mode-sse-kms.tf │ │ ├── enable-cache-encryption.tf │ │ ├── encrypted-ebs-volume.tf │ │ ├── encrypted-root-block-device.tf │ │ ├── instance-encrypted-block-device.tf │ │ ├── kinesis-stream-encryption.tf │ │ ├── msk-enable-in-transit-encryption.tf │ │ ├── rds-encrypt-cluster-storage-data.tf │ │ ├── rds-encrypt-instance-storage-data.tf │ │ ├── redshift-cluster-rest-encryption.tf │ │ ├── unencrypted-s3-bucket.tf │ │ └── workspaces-disk-encryption.tf │ ├── missing-threats-detection-and-alerts │ │ ├── aws-ecr-enable-image-scans.tf │ │ ├── azure-database-disabled-alerts.tf │ │ ├── azure-database-email-admin.tf │ │ ├── azure-database-email-for-alerts.tf │ │ ├── azure-security-center-alert-notifications.tf │ │ ├── azure-security-require-contact-phone.tf │ │ └── github-repo-vulnerability-alerts.tf │ ├── naming │ │ ├── aws-ec2-description-to-security-group-rule.tf │ │ ├── aws-ec2-description-to-security-group.tf │ │ ├── aws-elasticache-description-for-security-group.tf │ │ ├── google-gke-use-cluster-labels.tf │ │ ├── naming-rules-storage-accounts.tf │ │ └── openstack-networking-describe-security-group.tf │ ├── network-security-rules │ │ ├── aws-vpc-ec2-use-tcp.tf │ │ ├── azure-container-configured-network-policy.tf │ │ ├── azure-network-disable-rdp-from-internet.tf │ │ ├── azure-network-ssh-blocked-from-internet.tf │ │ ├── azure-storage-default-action-deny.tf │ │ ├── azure-synapse-virtual-network-enabled.tf │ │ ├── google-compute-no-serial-port.tf │ │ ├── google-gke-enable-ip-aliasing.tf │ │ ├── google-gke-enable-network-policy.tf │ │ └── google-iam-no-default-network.tf │ ├── permission-of-iam-policies │ │ ├── default-service-account-not-used-at-folder-level.tf │ │ ├── default-service-account-not-used-at-organization-level.tf │ │ ├── default-service-account-not-used-at-project-level.tf │ │ ├── google-iam-no-folder-level-service-account-impersonation.tf │ │ ├── google-iam-no-organization-level-service-account-impersonation.tf │ │ ├── google-iam-no-project-level-service-account-impersonation.tf │ │ ├── google-iam-no-user-granted-permissions.tf │ │ └── iam-policies-attached-only-to-groups-or-roles.tf │ ├── public-ip │ │ ├── google-compute-intance-with-public-ip.tf │ │ ├── lauch-configuration-public-ip-addr.tf │ │ ├── oracle-compute-no-public-ip.tf │ │ └── subnet-public-ip-address.tf │ ├── replication │ │ └── s3-bucket-cross-region-replication.tf │ ├── sensitive-action-by-iam │ │ └── aws-iam-no-policy-wildcards.tf │ ├── ssl-tls-mtls-policy │ │ ├── api-gateway-secure-tls-policy.tf │ │ ├── azure-appservice-require-client-cert.tf │ │ ├── azure-appservice-secure-tls-policy.tf │ │ ├── azure-storage-use-secure-tls-policy.tf │ │ ├── cloudfront-secure-tls-policy.tf │ │ ├── database-enable.ssl-eforcement.tf │ │ ├── database-secure-tls-policy.tf │ │ ├── elastic-search-secure-tls-policy.tf │ │ ├── elb-secure-tls-policy.tf │ │ ├── google-compute-secure-tls-policy.tf │ │ └── sql-encrypt-in-transit-data.tf │ ├── susp.tf │ ├── use-of-dns-without-dnssec │ │ └── cloud-dns-without-dnssec.tf │ ├── use-of-http-without-tls │ │ ├── aws-ssm-avoid-leaks-via-http.tf │ │ ├── azure-appservice-enforce-https.tf │ │ ├── azure-storage-enforce-https.tf │ │ ├── cloudfront-enforce-https.tf │ │ ├── digitalocean-compute-enforce-https.tf │ │ ├── elastic-search-enforce-https.tf │ │ └── elb-use-plain-http.tf │ ├── versioning │ │ ├── aws-s3-enable-versioning.tf │ │ └── digitalocean-spaces-versioning-enabled.tf │ ├── weak-password-key-policy │ │ ├── aws-iam-no-password-reuse.tf │ │ ├── aws-iam-require-lowercase-in-passwords.tf │ │ ├── aws-iam-require-numbers-in-passwords.tf │ │ ├── aws-iam-require-symbols-in-passwords.tf │ │ ├── aws-iam-require-uppercase-in-passwords.tf │ │ ├── aws-iam-set-max-password-age.tf │ │ ├── aws-iam-set-minimum-password-length.tf │ │ ├── azure-keyvault-ensure-key-expiration-date.tf │ │ ├── azure-keyvault-ensure-secret-expiry.tf │ │ └── azure-keyvault-no-purge.tf │ └── weak_crypt.tf │ └── test_security.py ├── images ├── structure.png └── tranformation_example.png ├── logo.png ├── poetry.lock ├── pyproject.toml ├── scripts ├── README.md ├── docker_images_scraper.py ├── obsolete_commads_scraper.py └── requirements.txt ├── stubs ├── ply │ ├── lex.pyi │ └── yacc.pyi ├── ruamel │ ├── __init__.pyi │ └── yaml │ │ ├── __init__.pyi │ │ ├── error.pyi │ │ ├── main.pyi │ │ ├── nodes.pyi │ │ └── tokens.pyi └── z3.pyi └── vscode-extension └── glitch ├── .eslintrc.json ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── images ├── feature.png └── logo.png ├── package-lock.json ├── package.json ├── src ├── diagnostics.ts ├── extension.ts └── test │ ├── runTest.ts │ └── suite │ ├── extension.test.ts │ └── index.ts ├── tsconfig.json └── vsc-extension-quickstart.md /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | lint: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3.5.2 16 | 17 | - name: Run linter 18 | uses: psf/black@stable 19 | with: 20 | options: "--check --verbose" 21 | version: "23.3.0" 22 | 23 | - name: Install Python 3 24 | uses: actions/setup-python@v4 25 | with: 26 | python-version: 3.10.5 27 | 28 | - name: Install dependencies pyright 29 | run: | 30 | python -m pip install --upgrade pip 31 | pip install pyright 32 | python -m pip install -e . 33 | 34 | - name: Run pyright 35 | run: pyright -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Run Python Tests 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: ruby/setup-ruby@v1 16 | with: 17 | ruby-version: '2.7.4' 18 | - name: Install Python 3 19 | uses: actions/setup-python@v4 20 | with: 21 | python-version: 3.10.5 22 | - name: Install dependencies 23 | run: | 24 | python -m pip install --upgrade pip 25 | python -m pip install -e . 26 | - name: Run tests with pytest 27 | run: | 28 | cd glitch 29 | python -m unittest discover tests -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | message: "If you use this software, please cite it as below." 3 | authors: 4 | - family-names: "Saavedra" 5 | given-names: "Nuno" 6 | orcid: "https://orcid.org/0000-0003-4148-5991" 7 | - family-names: "Ferreira" 8 | given-names: "João F." 9 | orcid: " https://orcid.org/0000-0002-6612-9013" 10 | title: "GLITCH" 11 | version: 1.0.0 12 | doi: 10.5281/zenodo.6670081 13 | date-released: 2022-06-20 14 | url: "https://github.com/sr-lab/GLITCH" 15 | -------------------------------------------------------------------------------- /configs/SLAC_chef.ini: -------------------------------------------------------------------------------- 1 | [security] 2 | suspicious_words = ["show_bug", "hack", "fixme", "later", "later2", "todo", 3 | "ticket", "launchpad", "bug"] 4 | passwords = ["pwd", "password", "pass"] 5 | users = ["username", "user"] 6 | secrets = ["key", "crypt", "secret", "certificate", "cert", "token", "ssh_key", 7 | "md5", "rsa", "ssl"] 8 | misc_secrets = [] 9 | roles = [] 10 | download_extensions = ["tgz", "tar.gz", "rpm", "dmg"] 11 | ssh_dirs = ["rsa", "ssh", "pem", "user", "root", "crt", "key", "ssl", "certificate", 12 | "crl", "pub", "id"] 13 | admin = ["admin"] 14 | checksum = ["checksum", "checksum_linux_x64", "checksum_linux_x86", 15 | "check_sha", "gcc_installer_checksum", "src_url", "repo_rpm_url", 16 | "gcc_installer_url", "url", "gpgcheck", "checksha", "repo_url", 17 | "package_url"] 18 | weak_crypt = ["md5", "base64"] 19 | weak_crypt_whitelist = [] 20 | url_http_white_list = [] -------------------------------------------------------------------------------- /configs/SLIC_puppet.ini: -------------------------------------------------------------------------------- 1 | [security] 2 | suspicious_words = ["hack", "fixme", "later", "later2", "todo", "ticket", "launchpad", 3 | "bug", "to-do"] 4 | passwords = ["pwd", "password", "pass"] 5 | users = ["user"] 6 | secrets = ["key", "crypt", "secret", "certificate", "cert", "ssh_key", "md5", 7 | "rsa", "ssl", "dsa", "ssh-rsa"] 8 | misc_secrets = [] 9 | roles = [] 10 | download_extensions = [] 11 | ssh_dirs = ["rsa", "ssh", "pem", "crt", "key", "ssl", "certificate", "crl", "pub", "rsa"] 12 | admin = ["admin"] 13 | checksum = [] 14 | weak_crypt = ["base64", "md5", "sha1"] 15 | weak_crypt_whitelist = [] 16 | url_http_white_list = [] -------------------------------------------------------------------------------- /configs/design_ansible.ini: -------------------------------------------------------------------------------- 1 | [design] 2 | exec_atomic_units = ["ansible.builtin.shell", "shell", "ansible.windows.win_shell", 3 | "win_shell", "ansible.builtin.command", "command", "ansible.windows.win_command", "win_command"] 4 | default_variables = [] -------------------------------------------------------------------------------- /configs/design_chef.ini: -------------------------------------------------------------------------------- 1 | [design] 2 | exec_atomic_units = ["bash", "execute"] 3 | default_variables = [] 4 | var_refer_symbol = "#" -------------------------------------------------------------------------------- /configs/design_puppet.ini: -------------------------------------------------------------------------------- 1 | [design] 2 | exec_atomic_units = ["exec"] 3 | default_variables = ["$name", "$title", "$server_facts", 4 | "$trusted", "$facts", "$authenticated", "$certname", "$domain", "$extensions", "$hostname"] 5 | var_refer_symbol = "" -------------------------------------------------------------------------------- /glitch/.gitignore: -------------------------------------------------------------------------------- 1 | examples/* 2 | -------------------------------------------------------------------------------- /glitch/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/__init__.py -------------------------------------------------------------------------------- /glitch/analysis/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/analysis/__init__.py -------------------------------------------------------------------------------- /glitch/analysis/design/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import List 3 | 4 | __all__: List[str] = [] 5 | for file in os.listdir(os.path.dirname(__file__)): 6 | if file.endswith(".py") and file != "__init__.py" and file != "visitor.py": 7 | __all__.append(file[:-3]) # type: ignore 8 | -------------------------------------------------------------------------------- /glitch/analysis/design/long_resource.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from glitch.analysis.rules import Error 3 | from glitch.analysis.design.smell_checker import DesignSmellChecker 4 | from glitch.analysis.design.visitor import DesignVisitor 5 | from glitch.repr.inter import * 6 | 7 | 8 | class TooManyVariables(DesignSmellChecker): 9 | def check(self, element: CodeElement, file: str) -> List[Error]: 10 | if isinstance(element, AtomicUnit) and element.type in DesignVisitor.EXEC: 11 | lines = 0 12 | for attr in element.attributes: 13 | for line in attr.code.split("\n"): 14 | if line.strip() != "": 15 | lines += 1 16 | 17 | if lines > 7: 18 | return [Error("design_long_resource", element, file, repr(element))] 19 | 20 | return [] 21 | -------------------------------------------------------------------------------- /glitch/analysis/design/long_statement.py: -------------------------------------------------------------------------------- 1 | from glitch.analysis.rules import Error 2 | from glitch.analysis.design.smell_checker import DesignSmellChecker 3 | from glitch.repr.inter import UnitBlockType 4 | from glitch.repr.inter import * 5 | 6 | 7 | class LongStatement(DesignSmellChecker): 8 | def check(self, element: CodeElement, file: str) -> List[Error]: 9 | errors: List[Error] = [] 10 | 11 | if isinstance(element, UnitBlock) and element.type != UnitBlockType.block: 12 | for i, line in enumerate(self.code_lines): 13 | if len(line) > 140: 14 | error = Error("implementation_long_statement", element, file, line) 15 | error.line = i + 1 16 | errors.append(error) 17 | 18 | return errors 19 | -------------------------------------------------------------------------------- /glitch/analysis/design/smell_checker.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, List 2 | from glitch.analysis.rules import SmellChecker 3 | from glitch.tech import Tech 4 | 5 | 6 | class DesignSmellChecker(SmellChecker): 7 | def __init__(self) -> None: 8 | super().__init__() 9 | self.code_lines: List[str] = [] 10 | self.variables_names: List[str] = [] 11 | 12 | @staticmethod 13 | def tech() -> Optional[Tech]: 14 | return None 15 | 16 | @staticmethod 17 | def ignore_techs() -> List[Tech]: 18 | return [] 19 | -------------------------------------------------------------------------------- /glitch/analysis/terraform/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import List 3 | 4 | __all__: List[str] = [] 5 | 6 | for file in os.listdir(os.path.dirname(__file__)): 7 | if file.endswith(".py") and file != "__init__.py": 8 | __all__.append(file[:-3]) # type: ignore 9 | -------------------------------------------------------------------------------- /glitch/files/obsolete_commands: -------------------------------------------------------------------------------- 1 | bfs 2 | cof2elf 3 | crypt 4 | cu 5 | face 6 | fmli 7 | fmtmsg 8 | fold 9 | ismpx 10 | jterm 11 | jwin 12 | layers 13 | lorder 14 | lptest 15 | mailalias 16 | newform 17 | newgrp 18 | news 19 | notify 20 | openwin 21 | pack 22 | pcat 23 | pg 24 | red 25 | relogin 26 | ruptime 27 | rwho 28 | shl 29 | sum 30 | tabs 31 | tsort 32 | unpack 33 | uucp 34 | uuglist 35 | uulog 36 | uuname 37 | uupick 38 | uustat 39 | uuto 40 | uux 41 | vacation 42 | vc 43 | whois 44 | write -------------------------------------------------------------------------------- /glitch/parsers/.gitignore: -------------------------------------------------------------------------------- 1 | parser.out 2 | parsetab.py 3 | -------------------------------------------------------------------------------- /glitch/parsers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/parsers/__init__.py -------------------------------------------------------------------------------- /glitch/parsers/resources/comments.rb.template: -------------------------------------------------------------------------------- 1 | require 'ripper' 2 | require 'pp' 3 | 4 | class CommentRipper < Ripper::SexpBuilder 5 | def on_comment(token) 6 | super.tap { |result| pp result } 7 | end 8 | end 9 | 10 | contents = File.read($path) 11 | pp CommentRipper.new(contents).parse -------------------------------------------------------------------------------- /glitch/repair/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/repair/__init__.py -------------------------------------------------------------------------------- /glitch/repair/interactive/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/repair/interactive/__init__.py -------------------------------------------------------------------------------- /glitch/repair/interactive/filesystem.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Optional 2 | from dataclasses import dataclass 3 | 4 | 5 | class State: 6 | def __str__(self) -> str: 7 | return self.__class__.__name__.lower() 8 | 9 | 10 | @dataclass 11 | class File(State): 12 | mode: Optional[str] 13 | owner: Optional[str] 14 | content: Optional[str] 15 | 16 | 17 | @dataclass 18 | class Dir(State): 19 | mode: Optional[str] 20 | owner: Optional[str] 21 | 22 | 23 | @dataclass 24 | class Nil(State): 25 | pass 26 | 27 | 28 | class FileSystemState: 29 | def __init__(self) -> None: 30 | self.state: Dict[str, State] = {} 31 | 32 | def copy(self): 33 | fs = FileSystemState() 34 | fs.state = self.state.copy() 35 | return fs 36 | -------------------------------------------------------------------------------- /glitch/repair/interactive/tracer/.gitignore: -------------------------------------------------------------------------------- 1 | parser.out 2 | parsetab.py 3 | lextab.py -------------------------------------------------------------------------------- /glitch/repair/interactive/values.py: -------------------------------------------------------------------------------- 1 | from glitch.repair.interactive.delta_p import * 2 | 3 | UNDEF = "glitch-undef" 4 | 5 | 6 | class DefaultValue: 7 | DEFAULT_MODE = PEConst(PStr("644")) 8 | DEFAULT_OWNER = PEConst(PStr("root")) 9 | DEFAULT_STATE = PEConst(PStr("present")) 10 | DEFAULT_CONTENT = PEUndef() 11 | -------------------------------------------------------------------------------- /glitch/repr/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/repr/__init__.py -------------------------------------------------------------------------------- /glitch/tech.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from typing import List 3 | 4 | 5 | class Tech(Enum): 6 | def __init__(self, tech: str, extensions: List[str]): 7 | self.tech = tech 8 | self.extensions = extensions 9 | 10 | ansible = "ansible", ["yml", "yaml"] 11 | chef = "chef", ["rb"] 12 | puppet = "puppet", ["pp"] 13 | terraform = "terraform", ["tf"] 14 | docker = "docker", ["Dockerfile"] 15 | gha = "github-actions", ["yml", "yaml"] 16 | -------------------------------------------------------------------------------- /glitch/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/__init__.py -------------------------------------------------------------------------------- /glitch/tests/cli/resources/chef_project/test.rb: -------------------------------------------------------------------------------- 1 | { 2 | "/etc/delivery/#{new_resource.chef_user}.pem" => new_resource.chef_user_pem, 3 | '/etc/chef/validation.pem' => new_resource.validation_pem, 4 | }.each do |file, src| 5 | chef_file file do 6 | sensitive new_resource.sensitive if new_resource.sensitive 7 | source src 8 | user 'root' 9 | group 'root' 10 | mode '0644' 11 | end 12 | end -------------------------------------------------------------------------------- /glitch/tests/design/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/design/__init__.py -------------------------------------------------------------------------------- /glitch/tests/design/ansible/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/design/ansible/__init__.py -------------------------------------------------------------------------------- /glitch/tests/design/ansible/design_ansible.ini: -------------------------------------------------------------------------------- 1 | [design] 2 | exec_atomic_units = ["ansible.builtin.shell", "shell", "ansible.windows.win_shell", 3 | "win_shell", "ansible.builtin.command", "command", "ansible.windows.win_command", "win_command"] 4 | default_variables = [] -------------------------------------------------------------------------------- /glitch/tests/design/ansible/files/avoid_comments.yml: -------------------------------------------------------------------------------- 1 | # TEST 2 | - name: (Windows) PRE-CHECK GitLab Runner exists 3 | block: 4 | - name: (Windows) Check gitlab-runner executable exists 5 | win_stat: 6 | path: "{{ gitlab_runner_executable }}" 7 | register: gitlab_runner_exists 8 | 9 | - name: (Windows) Set fact -> gitlab_runner_exists 10 | set_fact: 11 | gitlab_runner_exists: "{{ gitlab_runner_exists.stat.exists }}" # TEST -------------------------------------------------------------------------------- /glitch/tests/design/ansible/files/improper_alignment.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: iptables 3 | shell: "iptables -F && iptables -X \ 4 | && iptables -F -t nat && iptables -X -t nat \ 5 | && iptables -F -t raw && iptables -X -t raw \ 6 | && iptables -F -t mangle && iptables -X -t mangle" -------------------------------------------------------------------------------- /glitch/tests/design/ansible/files/long_statement.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: protect sysctl.conf 3 | file: 4 | path: '/etc/sysctl.conf' 5 | owner: 'root' 6 | group: 'root' 7 | mode: '0440' 8 | 9 | - name: set Daemon umask, do config for rhel-family | NSA 2.2.4.1 10 | template: 11 | src: 'etc/sysconfig/rhel_sysconfig_init.j2' 12 | dest: '/etc/sysconfig/init' 13 | owner: 'root' 14 | group: 'root' 15 | mode: '0544' 16 | when: ansible_distribution == 'RedHat' or ansible_distribution == 'Fedora' or ansible_distribution == 'CentOS' or ansible_distribution == 'Amazon' -------------------------------------------------------------------------------- /glitch/tests/design/ansible/files/multifaceted_abstraction.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get machine-id 3 | shell: >- 4 | hostnamectl --machine="{{ inventory_hostname }}" status | awk '/Machine ID/ {print $3}' 5 | register: _container_machine_id 6 | delegate_to: "{{ physical_host }}" -------------------------------------------------------------------------------- /glitch/tests/design/ansible/files/too_many_variables.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | gather_facts: no 5 | vars: 6 | aqua_admin_password: "{{ lookup('env', 'AQUA_ADMIN_PASSWORD') }}" 7 | aqua_sso_client_secret: "{{ lookup('env', 'AQUA_SSO_CLIENT_SECRET') }}" 8 | aqua_sso_client: "{{ lookup('env', 'AQUA_SSO_CLIENT') }}" 9 | aqua_scanner_username: "{{ lookup('env', 'AQUA_SCANNER_USERNAME') }}" 10 | aqua_scanner_password: "{{ lookup('env', 'AQUA_SCANNER_PASSWORD') }}" 11 | aqua_operator_username: "{{ lookup('env', 'AQUA_OPERATOR_USERNAME') }}" 12 | aqua_operator_passowrd: "{{ lookup('env', 'AQUA_OPERATOR_PASSWORD') }}" 13 | tasks: 14 | - include_tasks: tasks/login.yaml 15 | - include_tasks: tasks/enable_oidc.yaml 16 | - include_tasks: tasks/create_users.yaml 17 | - include_tasks: tasks/enable_enforcers.yaml 18 | - include_tasks: tasks/create_registries.yaml -------------------------------------------------------------------------------- /glitch/tests/design/chef/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/design/chef/__init__.py -------------------------------------------------------------------------------- /glitch/tests/design/chef/design_chef.ini: -------------------------------------------------------------------------------- 1 | [design] 2 | exec_atomic_units = ["bash", "execute"] 3 | var_refer_symbol = "#" 4 | default_variables = [] -------------------------------------------------------------------------------- /glitch/tests/design/chef/files/avoid_comments.rb: -------------------------------------------------------------------------------- 1 | include_recipe "nginx" 2 | 3 | directory '/var/run/pypi' do 4 | owner 'www-data' 5 | end 6 | 7 | # Install the pypi.python.org site 8 | template "#{node['nginx']['dir']}/sites-available/pypi.conf" do 9 | source "nginx_pypi.conf.erb" 10 | 11 | owner "root" 12 | group "root" 13 | mode "644" 14 | 15 | variables ({ 16 | :domains => [ 17 | "pypi.python.org", "cheeseshop.python.org", "a.pypi.python.org", 18 | "b.pypi.python.org", "d.pypi.python.org", "g.pypi.python.org", 19 | ], 20 | :root_dir => "/data/www/pypi", 21 | :packages_dir => "/data/packages", 22 | :static_dir => "/data/pypi/static", 23 | :hsts_seconds => 31536000, 24 | :uwsgi_sock => "unix:/var/run/pypi/pypi.sock", 25 | :upload_size => "100M", 26 | :default_server => true, 27 | }) 28 | 29 | notifies :reload, resources(:service => 'nginx') 30 | end -------------------------------------------------------------------------------- /glitch/tests/design/chef/files/duplicate_block.rb: -------------------------------------------------------------------------------- 1 | cron_d "staging-pycon-account-expunge" do 2 | hour "0" 3 | minute "0" 4 | command "bash -c 'source /srv/staging-pycon.python.org/shared/.env && cd /srv/staging-pycon.python.org/current && /srv/staging-pycon.python.org/shared/env/bin/python manage.py expunge_deleted'" 5 | end 6 | 7 | cron_d "staging-pycon-update-tutorial-registrants" do 8 | hour "0" 9 | minute "20" 10 | command "bash -c 'source /srv/staging-pycon.python.org/shared/.env && cd /srv/staging-pycon.python.org/current && /srv/staging-pycon.python.org/shared/env/bin/python manage.py update_tutorial_registrants'" 11 | end -------------------------------------------------------------------------------- /glitch/tests/design/chef/files/improper_alignment.rb: -------------------------------------------------------------------------------- 1 | yum_repository 'datadog' do 2 | name 'datadog' 3 | description 'datadog' 4 | proxy node['datadog']['yumrepo_proxy'] 5 | proxy_username node['datadog']['yumrepo_proxy_username'] 6 | proxy_password node['datadog']['yumrepo_proxy_password'] 7 | gpgkey node['datadog']['yumrepo_gpgkey'] 8 | gpgcheck true 9 | action :create 10 | end -------------------------------------------------------------------------------- /glitch/tests/design/chef/files/long_resource.rb: -------------------------------------------------------------------------------- 1 | execute "create ssh keypair for #{new_resource.username}" do 2 | cwd my_home 3 | user new_resource.username 4 | command <<-KEYGEN.gsub(/^ +/, '') 5 | ssh-keygen -t dsa -f #{my_home}/.ssh/id_dsa -N '' \ 6 | -C '#{new_resource.username}@#{fqdn}-#{Time.now.strftime('%FT%T%z')}' 7 | chmod 0600 #{my_home}/.ssh/id_dsa 8 | chmod 0644 #{my_home}/.ssh/id_dsa.pub 9 | KEYGEN 10 | action :nothing 11 | 12 | creates "#{my_home}/.ssh/id_dsa" 13 | end -------------------------------------------------------------------------------- /glitch/tests/design/chef/files/long_statement.rb: -------------------------------------------------------------------------------- 1 | Chef::Log.debug("Found chef-client in #{client_bin}") 2 | node.default['chef_client']['bin'] = client_bin 3 | create_directories 4 | 5 | execute "install #{node['chef_client']['svc_name']} in SRC" do 6 | command "mkssys -s #{node['chef_client']['svc_name']} -p #{node['chef_client']['bin']} -u root -S -n 15 -f 9 -o #{node['chef_client']['log_dir']}/client.log -e #{node['chef_client']['log_dir']}/client.log -a '-i #{node['chef_client']['interval']} -s #{node['chef_client']['splay']}'" 7 | not_if "lssrc -s #{node['chef_client']['svc_name']}" 8 | action :run 9 | end -------------------------------------------------------------------------------- /glitch/tests/design/chef/files/misplaced_attribute.rb: -------------------------------------------------------------------------------- 1 | template "/etc/rsyslog.d/remote.conf" do 2 | action :create 3 | source "rsyslog.d.remote.conf.erb" 4 | owner "root" 5 | group "root" 6 | mode "0644" 7 | cookbook 'logging_rsyslog' 8 | variables( 9 | :remote_server => remote_server 10 | ) 11 | end -------------------------------------------------------------------------------- /glitch/tests/design/chef/files/multifaceted_abstraction.rb: -------------------------------------------------------------------------------- 1 | execute "set initial migration level" do 2 | action :nothing 3 | command "cd /opt/opscode/embedded/service/partybus && ./bin/partybus init" 4 | subscribes :run, "file[#{OmnibusHelper.bootstrap_sentinel_file}]", :delayed 5 | end -------------------------------------------------------------------------------- /glitch/tests/design/chef/files/too_many_variables.rb: -------------------------------------------------------------------------------- 1 | define :sys_network_vlan_bridge, :interface => 'eth0' do 2 | vlan_id = params[:name] 3 | 4 | if vlan_id 5 | interface = params[:interface] 6 | vlan_interface = "#{interface}.#{vlan_id}" 7 | bridge = "br#{vlan_id}" 8 | if vlan_id == "0" 9 | node.default['sys']['network']['interfaces'][bridge] = { 10 | "bridge_ports" => interface 11 | } 12 | else 13 | node.default['sys']['network']['interfaces'][vlan_interface] = { 14 | "vlan-raw-device" => interface, 15 | "up" => "ifup #{bridge}" 16 | } 17 | node.default['sys']['network']['interfaces'][bridge] = { 18 | "auto" => false, 19 | "bridge_ports" => vlan_interface 20 | } 21 | end 22 | 23 | unless interface == node['network']['default_interface'] 24 | node.default['sys']['network']['interfaces'][interface] = { "inet" => "static" } 25 | end 26 | end 27 | end -------------------------------------------------------------------------------- /glitch/tests/design/docker/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/design/docker/__init__.py -------------------------------------------------------------------------------- /glitch/tests/design/docker/files/avoid_comments.Dockerfile: -------------------------------------------------------------------------------- 1 | # A ubuntu container 2 | FROM ubuntu:20.04 3 | USER ubuntu 4 | 5 | CMD ['echo', "Hello"] -------------------------------------------------------------------------------- /glitch/tests/design/docker/files/duplicate_block.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | USER ubuntu 3 | 4 | RUN wget https://repo.continuum.io/archive/Anaconda3-5.0.1-Linux-x86_64.sh && \ 5 | gpg Anaconda3-5.0.1-Linux-x86_64.sh && \ 6 | sh Anaconda3-5.0.1-Linux-x86_64.sh 7 | CMD ['echo', "Hello"] 8 | 9 | FROM ubuntu:20.04 10 | USER ubuntu 11 | 12 | RUN wget https://repo.continuum.io/archive/Anaconda3-5.0.1-Linux-x86_64.sh && \ 13 | gpg Anaconda3-5.0.1-Linux-x86_64.sh && \ 14 | sh Anaconda3-5.0.1-Linux-x86_64.sh 15 | CMD ['echo', "Hello"] 16 | -------------------------------------------------------------------------------- /glitch/tests/design/docker/files/improper_alignment.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | USER ubuntu 3 | 4 | RUN foo bar --a b \ 5 | --c d 6 | -------------------------------------------------------------------------------- /glitch/tests/design/docker/files/long_statement.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | USER ubuntu 3 | 4 | RUN cURL -X POST -d '{"name": "cURL", "type": "article"}' -H 'Accept-Encoding: application/json' -H 'Authorization: Bearer token' https://www.curl_blog.com/posts 5 | 6 | CMD ['echo', "Hello"] -------------------------------------------------------------------------------- /glitch/tests/design/docker/files/too_many_variables.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | USER ubuntu 3 | 4 | ARG aqua_admin_password 5 | ARG aqua_sso_client_secret 6 | ARG aqua_sso_client 7 | ARG aqua_scanner_username 8 | ARG aqua_scanner_password 9 | ARG aqua_operator_username 10 | ARG aqua_operator_passowrd -------------------------------------------------------------------------------- /glitch/tests/design/gha/files/too_many_variables.yml: -------------------------------------------------------------------------------- 1 | name: Package and Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - '**' 7 | workflow_dispatch: 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | env: 13 | CF_API_KEY: ${{ secrets.CF_API_KEY }} 14 | WAGO_API_TOKEN: ${{ secrets.WAGO_API_TOKEN }} 15 | GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }} 16 | -------------------------------------------------------------------------------- /glitch/tests/design/puppet/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/design/puppet/__init__.py -------------------------------------------------------------------------------- /glitch/tests/design/puppet/design_puppet.ini: -------------------------------------------------------------------------------- 1 | [design] 2 | exec_atomic_units = ["exec"] 3 | var_refer_symbol = "" 4 | default_variables = ["$name", "$title", "$server_facts", 5 | "$trusted", "$facts", "$authenticated", "$certname", "$domain", "$extensions", "$hostname"] -------------------------------------------------------------------------------- /glitch/tests/design/puppet/files/avoid_comments.pp: -------------------------------------------------------------------------------- 1 | class contrail::collector::service( 2 | $contrail_logoutput = $::contrail::params::contrail_logoutput, 3 | $redis_service = $::contrail::params::redis_service 4 | ) { 5 | # Ensure the services needed are running. 6 | exec { 'redis-del-db-dir': 7 | command => 'rm -f /var/lib/redis/dump.rb', 8 | provider => shell, 9 | logoutput => $contrail_logoutput 10 | } -> 11 | service { [$redis_service, 'supervisor-analytics'] : 12 | ensure => running, 13 | enable => true, 14 | } 15 | } -------------------------------------------------------------------------------- /glitch/tests/design/puppet/files/duplicate_block.pp: -------------------------------------------------------------------------------- 1 | node 'demo-server2.demo.juniper.net' { 2 | stage{ 'first': } 3 | stage{ 'last': } 4 | stage{ 'compute': } 5 | Stage['first']->Stage['main']->Stage['last']->Stage['compute'] 6 | class { '::contrail::profile::common' : stage => 'first' } 7 | class { '::contrail::profile::compute' : stage => 'compute' } 8 | } 9 | 10 | node 'demo-server1.demo.juniper.net' { 11 | stage{ 'first': } 12 | stage{ 'last': } 13 | stage{ 'compute': } 14 | Stage['first']->Stage['main']->Stage['last']->Stage['compute'] 15 | class { '::contrail::profile::common' : stage => 'first' } 16 | include ::contrail::profile::keepalived 17 | include ::contrail::profile::haproxy 18 | include ::contrail::profile::database 19 | include ::contrail::profile::webui 20 | include ::contrail::profile::openstack_controller 21 | include ::contrail::profile::config 22 | include ::contrail::profile::controller 23 | include ::contrail::profile::collector 24 | class { '::contrail::profile::provision' : stage => 'last' } 25 | } -------------------------------------------------------------------------------- /glitch/tests/design/puppet/files/improper_alignment.pp: -------------------------------------------------------------------------------- 1 | class { 'profile::icinga2::agent': 2 | endpoints => { 3 | 'NodeName' => {}, 4 | 'satellite.example.org' => { 5 | 'host' => '172.16.2.11', 6 | }, 7 | }, 8 | zones => { 9 | 'ZoneName' => { 10 | 'endpoints' => ['NodeName'], 11 | 'parent' => 'dmz', 12 | }, 13 | 'dmz' => { 14 | 'endpoints' => ['satellite.example.org'], 15 | }, 16 | }, 17 | } -------------------------------------------------------------------------------- /glitch/tests/design/puppet/files/long_resource.pp: -------------------------------------------------------------------------------- 1 | exec { 'storage_lm_boot_flag' : 2 | command => "/bin/true # comment to satisfy puppet syntax requirements 3 | set -x 4 | ifconfig livemnfsvgw 5 | RETVAL=\$? 6 | if [ \${RETVAL} -eq 0 ] 7 | then 8 | openstack-config --set /etc/nova/nova.conf DEFAULT resume_guests_state_on_host_boot True 9 | fi 10 | #ensure we return success always 11 | exit 0 12 | ", 13 | logoutput => $contrail_logoutput, 14 | } -------------------------------------------------------------------------------- /glitch/tests/design/puppet/files/long_statement.pp: -------------------------------------------------------------------------------- 1 | oneview_volume{'volume_5': 2 | ensure => 'get_attachable_volumes', 3 | require => Oneview_volume['volume_4'], 4 | data => { 5 | query_parameters => { 6 | connections => "[{'networkUri':'/rest/fc-networks/90bd0f63-3aab-49e2-a45f-a52500b46616','proxyName':'20:19:50:EB:1A:0F:0E:B6','initiatorName':'10:00:62:01:F8:70:00:0E'}]" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /glitch/tests/design/puppet/files/misplaced_attribute.pp: -------------------------------------------------------------------------------- 1 | file { "/etc/apt/preferences.d/${name}.pref": 2 | content => template('openstack/apt-pinning.pref.erb'), 3 | ensure => "present", 4 | } -------------------------------------------------------------------------------- /glitch/tests/design/puppet/files/multifaceted_abstraction.pp: -------------------------------------------------------------------------------- 1 | exec { 'clear_out_files' : 2 | command => 'rm -f /etc/contrail/contrail*.out && rm -f /opt/contrail/contrail_packages/exec-contrail-setup-sh.out && echo reset_provision_3_0 >> /etc/contrail/contrail_common_exec.out', 3 | unless => 'grep -qx reset_provision_3_0 /etc/contrail/contrail_common_exec.out', 4 | provider => shell, 5 | logoutput => $contrail_logoutput 6 | } -------------------------------------------------------------------------------- /glitch/tests/design/puppet/files/too_many_variables.pp: -------------------------------------------------------------------------------- 1 | class php::config { 2 | require boxen::config 3 | 4 | $root = "${boxen::config::home}/phpenv" 5 | $logdir = "${boxen::config::logdir}/php" 6 | $configdir = "${boxen::config::configdir}/php" 7 | $datadir = "${boxen::config::datadir}/php" 8 | $pluginsdir = "${root}/plugins" 9 | $cachedir = "${php::config::datadir}/cache" 10 | $extensioncachedir = "${php::config::datadir}/cache/extensions" 11 | } -------------------------------------------------------------------------------- /glitch/tests/design/puppet/files/unguarded_variable.pp: -------------------------------------------------------------------------------- 1 | define contrail::lib::setup_passthrough_white_list( 2 | $dev_name, 3 | ) { 4 | $physnet = $title 5 | exec { "config_pci_whitelist_${title}": 6 | command => "openstack-config --set /etc/nova/nova.conf DEFAULT pci_passthrough_whitelist ${wl}", 7 | provider => shell, 8 | logoutput => true 9 | } 10 | 11 | $nova_pci_passthrough_whitelist_params = { 12 | 'pci_passthrough_whitelist' => { value => '{ "devname": $dev_name, "physical_network": $physnet}'} 13 | } 14 | } -------------------------------------------------------------------------------- /glitch/tests/design/terraform/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/design/terraform/__init__.py -------------------------------------------------------------------------------- /glitch/tests/design/terraform/files/avoid_comments.tf: -------------------------------------------------------------------------------- 1 | resource "openstack_compute_instance_v2" "example" { 2 | name = "basic" # name 3 | image_id = "ad091b52-742f-469e-8f3c-fd81cadf0743" 4 | flavor_id = "3" 5 | security_groups = ["default"] 6 | user_data = "#cloud-config\nhostname: instance_1.example.com\nfqdn: instance_1.example.com" 7 | 8 | # hack 9 | network { 10 | name = "my_network" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /glitch/tests/design/terraform/files/duplicate_block.tf: -------------------------------------------------------------------------------- 1 | resource "openstack_compute_instance_v2" "example" { 2 | name = "basic" 3 | image_id = "ad091b52-742f-469e-8f3c-fd81cadf0743" 4 | flavor_id = "3" 5 | security_groups = ["default"] 6 | user_data = "#cloud-config\nhostname: instance_1.example.com\nfqdn: instance_1.example.com" 7 | 8 | } 9 | 10 | resource "openstack_compute_instance_v2" "example2" { 11 | name = "basic" 12 | image_id = "ad091b52-742f-469e-8f3c-fd81cadf0743" 13 | flavor_id = "3" 14 | security_groups = ["default"] 15 | user_data = "#cloud-config\nhostname: instance_1.example.com\nfqdn: instance_1.example.com" 16 | 17 | network { 18 | name = "my_network" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /glitch/tests/design/terraform/files/improper_alignment.tf: -------------------------------------------------------------------------------- 1 | resource "openstack_compute_instance_v2" "example" { 2 | name = "basic" 3 | image_id = "ad091b52-742f-469e-8f3c-fd81cadf0743" 4 | flavor_id = "3" 5 | security_groups = ["default"] 6 | user_data = "#cloud-config\nhostname: instance_1.example.com\nfqdn: instance_1.example.com" 7 | } -------------------------------------------------------------------------------- /glitch/tests/design/terraform/files/long_statement.tf: -------------------------------------------------------------------------------- 1 | resource "openstack_compute_instance_v2" "example" { 2 | name = "basic" 3 | image_id = "ad091b52-742f-469e-8f3c-fd81cadf0743" 4 | flavor_id = "3" 5 | security_groups = ["default"] 6 | user_data = "#cloud-config\nhostname: instance_1.example.com\nfqdn: instance_1.exampleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.com" 7 | } -------------------------------------------------------------------------------- /glitch/tests/design/terraform/files/too_many_variables.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | instance_ids = concat(aws_instance.blue.*.id, aws_instance.green.*.id) 3 | } 4 | 5 | locals { 6 | labels1 = ["default", {yes = "yes"}, "hello"] 7 | 8 | common_tags = { 9 | Service = local.service_name 10 | Owner = local.owner 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /glitch/tests/hierarchical/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/hierarchical/__init__.py -------------------------------------------------------------------------------- /glitch/tests/hierarchical/ansible/attributes.yml: -------------------------------------------------------------------------------- 1 | - name: Calculate factorial of a number 2 | hosts: localhost 3 | debug: 4 | msg: "The factorial of 5 is {{ factorial_value }}" 5 | seq: [test: "something", "y", "z"] 6 | hash: {test1: "1", test2: "2"} 7 | -------------------------------------------------------------------------------- /glitch/tests/hierarchical/ansible/vars.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test: 3 | - test1: 4 | - [1, 2] 5 | - [3, 4] 6 | - x 7 | - y 8 | - 23 9 | 10 | test2: 11 | - [2, 5, 6] 12 | 13 | vars: 14 | factorial_of: 5 15 | factorial_value: 1 -------------------------------------------------------------------------------- /glitch/tests/hierarchical/chef/vars.rb: -------------------------------------------------------------------------------- 1 | grades = { "Jane Doe" => 10, "Jim Doe" => 6 } 2 | default[:zabbix][:database][:password] = nil 3 | default[:zabbix][:test][:name] = "something" -------------------------------------------------------------------------------- /glitch/tests/hierarchical/puppet/vars.pp: -------------------------------------------------------------------------------- 1 | $my_hash = { 2 | 'key1' => { 3 | 'test1' => '1', 4 | 'test2' => '2', 5 | }, 6 | 'key2' => 'value2', 7 | 'key3' => 'value3', 8 | } 9 | 10 | $my_hash['key4']['key5'] = 'value5' 11 | 12 | $configdir = "${boxen::config::configdir}/php" 13 | $datadir = "${boxen::config::datadir}/php" 14 | $pluginsdir = "${root}/plugins" 15 | $cachedir = "${php::config::datadir}/cache" 16 | $extensioncachedir = "${php::config::datadir}/cache/extensions" 17 | -------------------------------------------------------------------------------- /glitch/tests/parser/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/parser/__init__.py -------------------------------------------------------------------------------- /glitch/tests/parser/gha/files/index_out_of_range.yml: -------------------------------------------------------------------------------- 1 | name: Package and Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - '**' 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Clone 14 | uses: actions/checkout@v1 15 | 16 | - name: test 17 | uses: test 18 | with: 19 | args: test 20 | -------------------------------------------------------------------------------- /glitch/tests/parser/gha/files/valid_workflow.yml: -------------------------------------------------------------------------------- 1 | name: Run Python Tests 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: ruby/setup-ruby@v1 16 | with: 17 | ruby-version: '2.7.4' 18 | - name: Install Python 3 19 | uses: actions/setup-python@v4 20 | with: 21 | python-version: 3.10.5 22 | - name: Install dependencies 23 | run: | 24 | python -m pip install --upgrade pip 25 | python -m pip install -e . 26 | - name: Run tests with pytest 27 | run: | 28 | cd glitch 29 | python -m unittest discover tests -------------------------------------------------------------------------------- /glitch/tests/parser/puppet/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/parser/puppet/__init__.py -------------------------------------------------------------------------------- /glitch/tests/parser/puppet/files/if.pp: -------------------------------------------------------------------------------- 1 | if $x == 'absent' { 2 | file {'/usr/sbin/policy-rc.d': 3 | ensure => absent, 4 | } 5 | } else { 6 | file {'/usr/sbin/policy-rc.d': 7 | ensure => present, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /glitch/tests/parser/puppet/test_parser.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from glitch.parsers.puppet import PuppetParser 3 | from glitch.repr.inter import * 4 | 5 | 6 | class TestPuppetParser(unittest.TestCase): 7 | def test_puppet_parser_if(self) -> None: 8 | unit_block = PuppetParser().parse_file("tests/parser/puppet/files/if.pp", None) 9 | assert len(unit_block.statements) == 1 10 | assert isinstance(unit_block.statements[0], ConditionalStatement) 11 | # FIXME: the expression should not be a string and or at least should be 12 | # equal to the script 13 | assert unit_block.statements[0].condition == "$x==absent" 14 | assert len(unit_block.statements[0].statements) == 1 15 | assert isinstance(unit_block.statements[0].statements[0], AtomicUnit) 16 | assert unit_block.statements[0].else_statement is not None 17 | assert isinstance(unit_block.statements[0].else_statement, ConditionalStatement) 18 | assert len(unit_block.statements[0].else_statement.statements) == 1 19 | assert isinstance( 20 | unit_block.statements[0].else_statement.statements[0], AtomicUnit 21 | ) 22 | -------------------------------------------------------------------------------- /glitch/tests/parser/terraform/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/parser/terraform/__init__.py -------------------------------------------------------------------------------- /glitch/tests/parser/terraform/files/boolean_value_assign.tf: -------------------------------------------------------------------------------- 1 | resource "google_service_account" "bqowner" { 2 | account_id = true 3 | } 4 | -------------------------------------------------------------------------------- /glitch/tests/parser/terraform/files/comments.tf: -------------------------------------------------------------------------------- 1 | #comment1 2 | //comment2 3 | resource "google_bigquery_dataset" "dataset" { 4 | /*comment3 5 | default_table_expiration_ms = 3600000 6 | 7 | finish comment3 */ #comment4 8 | 9 | default_table_expiration_ms = 3600000 #comment5 10 | 11 | labels = { 12 | env = "default" #comment inside dict 13 | //comment2 inside dict 14 | test = "value1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /glitch/tests/parser/terraform/files/dict_value_assign.tf: -------------------------------------------------------------------------------- 1 | resource "google_bigquery_dataset" "dataset" { 2 | labels = { 3 | env = "default" 4 | } 5 | } -------------------------------------------------------------------------------- /glitch/tests/parser/terraform/files/dynamic_block.tf: -------------------------------------------------------------------------------- 1 | resource "aws_elastic_beanstalk_environment" "tfenvtest" { 2 | dynamic "setting" { 3 | content { 4 | namespace = setting.value["namespace"] 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /glitch/tests/parser/terraform/files/empty_string_assign.tf: -------------------------------------------------------------------------------- 1 | resource "google_service_account" "bqowner" { 2 | account_id = "" 3 | } 4 | -------------------------------------------------------------------------------- /glitch/tests/parser/terraform/files/list_value_assign.tf: -------------------------------------------------------------------------------- 1 | resource "google_service_account" "bqowner" { 2 | keys = ["value1", [1, {key2 = "value2"}], {key3 = "value3"}] 3 | } 4 | -------------------------------------------------------------------------------- /glitch/tests/parser/terraform/files/multiline_string_assign.tf: -------------------------------------------------------------------------------- 1 | resource "aws_instance" "example" { 2 | user_data = < new_resource.chef_user_pem, 3 | '/etc/chef/validation.pem' => new_resource.validation_pem, 4 | }.each do |file, src| 5 | chef_file file do 6 | sensitive new_resource.sensitive if new_resource.sensitive 7 | source src 8 | user 'root' 9 | group 'root' 10 | mode '0644' 11 | end 12 | end -------------------------------------------------------------------------------- /glitch/tests/security/chef/files/empty.rb: -------------------------------------------------------------------------------- 1 | default[:zabbix][:database][:password] = nil -------------------------------------------------------------------------------- /glitch/tests/security/chef/files/full_permission.rb: -------------------------------------------------------------------------------- 1 | file 'foo' do 2 | content 'bar' 3 | mode '0777' 4 | owner 'foo' 5 | group 'foo' 6 | end -------------------------------------------------------------------------------- /glitch/tests/security/chef/files/hard_secr.rb: -------------------------------------------------------------------------------- 1 | user 'osmdata' do 2 | supports :manage_home => true 3 | comment 'osm data' 4 | uid '1201' 5 | gid 'osmdata' 6 | shell '/bin/bash' 7 | home '/home/osmdata' 8 | password '$1$gkl9sSWg$U9aIhckrcXwr08PLbx7NG1' 9 | system false 10 | action :create 11 | not_if "getent passwd osmdata" 12 | end -------------------------------------------------------------------------------- /glitch/tests/security/chef/files/http.rb: -------------------------------------------------------------------------------- 1 | default[:social_graph][:deploy_path] = "/data/apps/social_graph" 2 | default[:social_graph][:version] = "1.0.8" 3 | default[:social_graph][:url] = "http://files.ihrdev.com/jobs/social_graph" -------------------------------------------------------------------------------- /glitch/tests/security/chef/files/int_check.rb: -------------------------------------------------------------------------------- 1 | remote_file "#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz" do 2 | action :create_if_missing 3 | source "https://download.civicrm.org/civicrm-#{civicrm_version}-l10n.tar.gz" 4 | owner "wordpress" 5 | group "wordpress" 6 | mode "644" 7 | backup false 8 | end -------------------------------------------------------------------------------- /glitch/tests/security/chef/files/inv_bind.rb: -------------------------------------------------------------------------------- 1 | default['ossec']['conf']['cluster'] = { 2 | 'name' => 'wazuh', 3 | 'node_name' => 'node01', 4 | 'node_type' => 'master', 5 | 'key' => '', 6 | 'port' => 1516, 7 | 'bind_addr' => '0.0.0.0', 8 | 'nodes' => { 9 | 'node' => "NODE_IP" 10 | }, 11 | 'hidden' => false, 12 | 'disabled' => true 13 | } 14 | -------------------------------------------------------------------------------- /glitch/tests/security/chef/files/missing_default.rb: -------------------------------------------------------------------------------- 1 | case node[:platform_family] 2 | when "rhel" 3 | default[:vmwaretools][:packages] = %w{ vmware-tools-core } 4 | when "debian" 5 | default[:vmwaretools][:packages] = %w{ } 6 | end -------------------------------------------------------------------------------- /glitch/tests/security/chef/files/obs_command.rb: -------------------------------------------------------------------------------- 1 | execute 'run_pack' do 2 | command 'pack foo bar' 3 | end -------------------------------------------------------------------------------- /glitch/tests/security/chef/files/susp.rb: -------------------------------------------------------------------------------- 1 | # Create/fix permissions on supplemental directories 2 | %w(cache lib run).each do |folder| 3 | directory "fix permissions for /var/#{folder}/jenkins" do 4 | path "/var/#{folder}/jenkins" 5 | owner node['jenkins']['master']['user'] 6 | group node['jenkins']['master']['group'] 7 | mode node['jenkins']['master']['mode'] 8 | action :create 9 | end 10 | end -------------------------------------------------------------------------------- /glitch/tests/security/chef/files/weak_crypt.rb: -------------------------------------------------------------------------------- 1 | def wildfly_user(user = nil, pass = nil, realm = 'ManagementRealm') 2 | user ||= 'chef-wildfly-' + SecureRandom.urlsafe_base64(5) 3 | pass ||= SecureRandom.urlsafe_base64(40) 4 | passhash = Digest::MD5.hexdigest "#{user}:#{realm}:#{pass}" 5 | { 6 | user: user.to_s, 7 | pass: pass.to_s, 8 | passhash: passhash.to_s, 9 | } 10 | end -------------------------------------------------------------------------------- /glitch/tests/security/docker/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/security/docker/__init__.py -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/admin.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python as builder 2 | USER root 3 | 4 | FROM ubuntu as runtime -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/empty.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python as builder 2 | USER builder 3 | 4 | ENV root_password "" -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/full_permission.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python as builder 2 | USER builder 3 | RUN chmod a+xrw Anaconda3-5.0.1-Linux-x86_64.sh -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/hard_secr.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres 2 | USER builder 3 | ENV POSTGRES_PASSWORD "password" -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/http.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python as builder 2 | USER builder 3 | 4 | ARG URL 5 | RUN curl http://$URL.com 6 | -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/int_check.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | USER ubuntu 3 | RUN wget https://repo.continuum.io/archive/Anaconda3-5.0.1-Linux-x86_64.sh 4 | RUN wget https://repo.continuum.io/archive/Anaconda3-5-Linux-x86_64.sh 5 | 6 | RUN gpg Anaconda3-5.0.1-Linux-x86_64.sh -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/inv_bind.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | USER ubuntu 3 | 4 | CMD ["uvicorn", "--host", "0.0.0.0", "main:app"] -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/non_off_image.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/maksynbilenko/oracle-12c-base:latest 2 | USER user -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/obs_command.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | USER ubuntu 3 | 4 | RUN pack foo bar -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/susp.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | USER ubuntu 3 | # TODO: Implement missing features -------------------------------------------------------------------------------- /glitch/tests/security/docker/files/weak_crypt.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | USER ubuntu 3 | 4 | ARG USER 5 | ARG PASS 6 | 7 | RUN useradd -h $USER 8 | RUN usermod -p $(mkpasswd -H md5 $PASS) $USER 9 | -------------------------------------------------------------------------------- /glitch/tests/security/puppet/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/security/puppet/__init__.py -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/admin.pp: -------------------------------------------------------------------------------- 1 | class aptly ( 2 | String $package_ensure = 'present', 3 | Stdlib::Absolutepath $config_file = '/etc/aptly.conf', 4 | Hash $config = {}, 5 | Optional[String] $config_contents = undef, 6 | Boolean $repo = true, 7 | String $user = 'root', 8 | Hash $aptly_repos = {}, 9 | Hash $aptly_mirrors = {}, 10 | ) { 11 | if $repo { 12 | Apt::Source['aptly'] -> Class['apt::update'] -> Package['aptly'] 13 | } 14 | 15 | package { 'aptly': 16 | ensure => $package_ensure, 17 | } 18 | 19 | $config_file_contents = $config_contents ? { 20 | undef => inline_template("<%= Hash[@config.sort].to_pson %>\n"), 21 | default => $config_contents, 22 | } 23 | 24 | file { $config_file: 25 | ensure => file, 26 | content => $config_file_contents, 27 | } 28 | 29 | $aptly_cmd = "/usr/bin/aptly -config ${config_file}" 30 | 31 | create_resources('::aptly::mirror', $aptly_mirrors) 32 | } -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/empty.pp: -------------------------------------------------------------------------------- 1 | define mysql::server::instance ($root_password = '', $debian_sys_maint_password = '') { 2 | 3 | class { 'mysql::server': 4 | root_password => $root_password, 5 | debian_sys_maint_password => $debian_sys_maint_password, 6 | } 7 | } -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/full_permission.pp: -------------------------------------------------------------------------------- 1 | file { '/etc/foo': 2 | ensure => file, 3 | target => '/etc/foo', 4 | mode => '0777', 5 | } -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/hard_secr.pp: -------------------------------------------------------------------------------- 1 | class component::postgresql ( 2 | $postgres_password = 'root', 3 | $postgis = false, 4 | $extensions = [], 5 | $databases = {} 6 | ) { 7 | validate_string($postgres_password) 8 | validate_array($extensions) 9 | validate_hash($databases) 10 | 11 | anchor { 'component::postgresql::begin': } -> 12 | class { '::postgresql::server': 13 | postgres_password => $postgres_password 14 | } -> 15 | anchor { 'component::postgresql::end': } 16 | 17 | contain '::postgresql::client' 18 | 19 | if $postgis { 20 | contain '::postgresql::server::postgis' 21 | } 22 | 23 | ensure_resource('package', $extensions, { 24 | require => Anchor['component::postgresql::begin'], 25 | before => Anchor['component::postgresql::end'] 26 | }) 27 | 28 | create_resources('::postgresql::server::db', $databases, { 29 | require => Anchor['component::postgresql::begin'], 30 | before => Anchor['component::postgresql::end'] 31 | }) 32 | } -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/http.pp: -------------------------------------------------------------------------------- 1 | class profile::monitoring::netdata::haproxy( 2 | $stats_url = "http://${::ipaddress_public1}:9000/;csv;norefresh" 3 | ) { 4 | 5 | file_line { 'netdata-haproxy': 6 | ensure => present, 7 | path => '/opt/netdata/netdata-configs/python.d/haproxy.conf', 8 | line => 'via_url:', 9 | match => '^via_url:', 10 | require => Class['netdata'] 11 | } -> 12 | file_line { 'netdata-haproxy-url': 13 | ensure => present, 14 | path => '/opt/netdata/netdata-configs/python.d/haproxy.conf', 15 | line => " url: '${stats_url}'", 16 | after => '^via_url:', 17 | require => Class['netdata'] 18 | } 19 | } -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/int_check.pp: -------------------------------------------------------------------------------- 1 | archive { $kib_name: 2 | ensure => present, 3 | url => $url, 4 | target => $extract_location, 5 | checksum => false, 6 | } 7 | 8 | file { "${app_root}/config.js": 9 | ensure => present, 10 | content => template('performanceplatform/kibana.config.js.erb'), 11 | require => Archive[$kib_name], 12 | } -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/inv_bind.pp: -------------------------------------------------------------------------------- 1 | class openstack::profile::firewall::post { 2 | firewall { '9100 - Accept all vm network traffic': 3 | proto => 'all', 4 | state => ['NEW'], 5 | action => 'accept', 6 | source => $::openstack::config::network_data, 7 | } -> 8 | firewall { '9999 - Reject remaining traffic': 9 | proto => 'all', 10 | action => 'reject', 11 | reject => 'icmp-host-prohibited', 12 | source => '0.0.0.0/0', 13 | } 14 | } -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/missing_default.pp: -------------------------------------------------------------------------------- 1 | $php_prefix = $::osfamily ? { 2 | 'debian' => 'php5-', 3 | 'redhat' => 'php-', 4 | } 5 | 6 | case $facts['os']['name'] { 7 | 'RedHat', 'CentOS': { include role::redhat } 8 | /^(Debian|Ubuntu)$/: { include role::debian } 9 | } 10 | -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/obs_command.pp: -------------------------------------------------------------------------------- 1 | exec { 'Running pack': 2 | command => 'pack foo bar', 3 | path => '/usr/bin:/usr/sbin:/bin', 4 | } -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/susp.pp: -------------------------------------------------------------------------------- 1 | define apache::mod ( 2 | $package = undef, 3 | $package_ensure = 'present', 4 | $lib = undef, 5 | $lib_path = $::apache::params::lib_path, 6 | $id = undef, 7 | $path = undef, 8 | ) { 9 | if ! defined(Class['apache']) { 10 | fail('You must include the apache base class before using any apache defined resources') 11 | } 12 | 13 | $mod = $name 14 | #include apache #This creates duplicate resources in rspec-puppet 15 | $mod_dir = $::apache::mod_dir 16 | 17 | # Determine if we have special lib 18 | $mod_libs = $::apache::params::mod_libs 19 | $mod_lib = $mod_libs[$mod] # 2.6 compatibility hack 20 | if $lib { 21 | $_lib = $lib 22 | } elsif $mod_lib { 23 | $_lib = $mod_lib 24 | } else { 25 | $_lib = "mod_${mod}.so" 26 | } 27 | } -------------------------------------------------------------------------------- /glitch/tests/security/puppet/files/weak_crypt.pp: -------------------------------------------------------------------------------- 1 | class govuk_postgresql::env_sync_user ( 2 | $password 3 | ) { 4 | @postgresql::server::role { 'env-sync': 5 | password_hash => postgresql_password('env-sync', $password), 6 | tag => 'govuk_postgresql::server::not_slave', 7 | } 8 | 9 | postgresql::server::pg_hba_rule { 'local access as env-sync user': 10 | type => 'local', 11 | database => 'all', 12 | auth_method => 'md5', 13 | order => '001', # necessary to ensure this is before the 'local all all ident' rule. 14 | } 15 | } -------------------------------------------------------------------------------- /glitch/tests/security/terraform/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/glitch/tests/security/terraform/__init__.py -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/admin.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_access_key" "example" { 2 | user = "root" 3 | } -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/disabled-authentication/azure-app-service-authentication-activated.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_app_service" "bad_example" { 2 | client_cert_enabled = true 3 | https_only = true 4 | } 5 | 6 | resource "azurerm_app_service" "bad_example2" { 7 | https_only = true 8 | client_cert_enabled = true 9 | 10 | auth_settings { 11 | enabled = false 12 | } 13 | } 14 | 15 | resource "azurerm_app_service" "good_example" { 16 | https_only = true 17 | client_cert_enabled = true 18 | 19 | auth_settings { 20 | enabled = true 21 | } 22 | } 23 | 24 | resource "azurerm_function_app" "good_example" { 25 | name = "example-app-service" 26 | location = azurerm_resource_group.example.location 27 | resource_group_name = azurerm_resource_group.example.name 28 | app_service_plan_id = azurerm_app_service_plan.example.id 29 | https_only = true 30 | 31 | auth_settings { 32 | enabled = true 33 | } 34 | } -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/disabled-authentication/disable-password-authentication.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_linux_virtual_machine" "bad_linux_example" { 2 | disable_password_authentication = false 3 | } 4 | 5 | resource "azurerm_linux_virtual_machine" "good_linux_example" { 6 | } 7 | 8 | resource "azurerm_linux_virtual_machine" "good_linux_example2" { 9 | disable_password_authentication = true 10 | } 11 | 12 | 13 | resource "azurerm_virtual_machine" "bad_example" { 14 | } 15 | 16 | resource "azurerm_virtual_machine" "bad_example" { 17 | os_profile_linux_config { 18 | disable_password_authentication = false 19 | } 20 | } 21 | 22 | resource "azurerm_virtual_machine" "good_example" { 23 | os_profile_linux_config { 24 | disable_password_authentication = true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/empty.tf: -------------------------------------------------------------------------------- 1 | resource "openstack_compute_instance_v2" "example" { 2 | name = "basic" 3 | image_id = "ad091b52-742f-469e-8f3c-fd81cadf0743" 4 | flavor_id = "3" 5 | admin_pass = "" 6 | security_groups = ["default"] 7 | user_data = "#cloud-config\nhostname: instance_1.example.com\nfqdn: instance_1.example.com" 8 | 9 | network { 10 | name = "my_network" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/firewall-misconfiguration/alb-drop-invalid-headers.tf: -------------------------------------------------------------------------------- 1 | resource "aws_alb" "bad_example" { 2 | internal = true 3 | } 4 | 5 | resource "aws_alb" "bad_example2" { 6 | internal = true 7 | drop_invalid_header_fields = false 8 | } 9 | 10 | resource "aws_alb" "good_example" { 11 | internal = true 12 | drop_invalid_header_fields = true 13 | } 14 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/firewall-misconfiguration/alb-exposed-to-internet.tf: -------------------------------------------------------------------------------- 1 | resource "aws_lb" "bad_example" { 2 | drop_invalid_header_fields = true 3 | } 4 | 5 | resource "aws_lb" "bad_example2" { 6 | drop_invalid_header_fields = true 7 | internal = false 8 | } 9 | 10 | resource "aws_lb" "good_example" { 11 | drop_invalid_header_fields = true 12 | internal = true 13 | } 14 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/firewall-misconfiguration/azure-keyvault-specify-network-acl.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_key_vault" "bad_example" { 2 | enabled_for_disk_encryption = true 3 | soft_delete_retention_days = 7 4 | purge_protection_enabled = true 5 | } 6 | 7 | resource "azurerm_key_vault" "bad_example2" { 8 | enabled_for_disk_encryption = true 9 | soft_delete_retention_days = 7 10 | purge_protection_enabled = true 11 | 12 | network_acls { 13 | default_action = "Allow" 14 | bypass = "AzureServices" 15 | } 16 | } 17 | 18 | resource "azurerm_key_vault" "good_example" { 19 | enabled_for_disk_encryption = true 20 | soft_delete_retention_days = 7 21 | purge_protection_enabled = true 22 | 23 | network_acls { 24 | default_action = "Deny" 25 | bypass = "AzureServices" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/firewall-misconfiguration/cloudfront-use-waf.tf: -------------------------------------------------------------------------------- 1 | resource "aws_cloudfront_distribution" "bad_example" { 2 | default_cache_behavior { 3 | viewer_protocol_policy = "redirect-to-https" 4 | } 5 | viewer_certificate { 6 | minimum_protocol_version = "tlsv1.2_2021" 7 | } 8 | logging_config { 9 | bucket = "some_bucket" 10 | } 11 | } 12 | 13 | resource "aws_cloudfront_distribution" "bad_example2" { 14 | web_acl_id = "" 15 | 16 | default_cache_behavior { 17 | viewer_protocol_policy = "redirect-to-https" 18 | } 19 | viewer_certificate { 20 | minimum_protocol_version = "tlsv1.2_2021" 21 | } 22 | logging_config { 23 | bucket = "some_bucket" 24 | } 25 | } 26 | 27 | resource "aws_cloudfront_distribution" "good_example" { 28 | web_acl_id = "waf_id" 29 | 30 | default_cache_behavior { 31 | viewer_protocol_policy = "redirect-to-https" 32 | } 33 | viewer_certificate { 34 | minimum_protocol_version = "tlsv1.2_2021" 35 | } 36 | logging_config { 37 | bucket = "some_bucket" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/firewall-misconfiguration/config-master-authorized-networks.tf: -------------------------------------------------------------------------------- 1 | resource "google_container_cluster" "bad_example" { 2 | private_cluster_config { 3 | enable_private_nodes = true 4 | } 5 | ip_allocation_policy {} 6 | network_policy { 7 | enabled = true 8 | } 9 | enable_legacy_abac = false 10 | resource_labels = { 11 | "env" = "staging" 12 | } 13 | } 14 | 15 | resource "google_container_cluster" "good_example" { 16 | master_authorized_networks_config { 17 | cidr_blocks { 18 | cidr_block = "0.1.0.0/24" 19 | } 20 | } 21 | 22 | private_cluster_config { 23 | enable_private_nodes = true 24 | } 25 | ip_allocation_policy {} 26 | network_policy { 27 | enabled = true 28 | } 29 | enable_legacy_abac = false 30 | resource_labels = { 31 | "env" = "staging" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/firewall-misconfiguration/google-compute-inbound-rule-traffic.tf: -------------------------------------------------------------------------------- 1 | resource "google_compute_firewall" "bad_example" { 2 | allow { 3 | protocol = "icmp" 4 | } 5 | destination_ranges = ["1.2.3.4/32"] 6 | } 7 | 8 | resource "google_compute_firewall" "good_example" { 9 | allow { 10 | protocol = "icmp" 11 | } 12 | source_ranges = ["1.2.3.4/32"] 13 | destination_ranges = ["1.2.3.4/32"] 14 | } 15 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/firewall-misconfiguration/google-compute-no-ip-forward.tf: -------------------------------------------------------------------------------- 1 | resource "google_compute_instance" "bad_example" { 2 | can_ip_forward = true 3 | 4 | metadata { 5 | block-project-ssh-keys = true 6 | } 7 | boot_disk { 8 | kms_key_self_link = "something" 9 | } 10 | service_account { 11 | email = "example@email.com" 12 | } 13 | } 14 | 15 | resource "google_compute_instance" "good_example" { 16 | metadata { 17 | block-project-ssh-keys = true 18 | } 19 | boot_disk { 20 | kms_key_self_link = "something" 21 | } 22 | service_account { 23 | email = "example@email.com" 24 | } 25 | } 26 | 27 | resource "google_compute_instance" "good_example2" { 28 | can_ip_forward = false 29 | metadata { 30 | block-project-ssh-keys = true 31 | } 32 | boot_disk { 33 | kms_key_self_link = "something" 34 | } 35 | service_account { 36 | email = "example@email.com" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/firewall-misconfiguration/google-compute-outbound-rule-traffic.tf: -------------------------------------------------------------------------------- 1 | resource "google_compute_firewall" "bad_example" { 2 | direction = "EGRESS" 3 | allow { 4 | protocol = "icmp" 5 | } 6 | source_ranges = ["1.2.3.4/32"] 7 | } 8 | 9 | resource "google_compute_firewall" "good_example" { 10 | direction = "EGRESS" 11 | allow { 12 | protocol = "icmp" 13 | } 14 | source_ranges = ["1.2.3.4/32"] 15 | destination_ranges = ["1.2.3.4/32"] 16 | } 17 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/firewall-misconfiguration/openstack-compute-no-public-access.tf: -------------------------------------------------------------------------------- 1 | resource "openstack_fw_rule_v1" "bad_example" { 2 | name = "my_rule" 3 | description = "let anyone in" 4 | action = "allow" 5 | protocol = "tcp" 6 | destination_port = "22" 7 | enabled = "true" 8 | } 9 | 10 | resource "openstack_fw_rule_v1" "bad_example2" { 11 | name = "my_rule" 12 | description = "don't let just anyone in" 13 | action = "allow" 14 | protocol = "tcp" 15 | destination_ip_address = "10.10.10.1" 16 | destination_port = "22" 17 | enabled = "true" 18 | } 19 | 20 | resource "openstack_fw_rule_v1" "good_example" { 21 | name = "my_rule" 22 | description = "don't let just anyone in" 23 | action = "allow" 24 | protocol = "tcp" 25 | destination_ip_address = "10.10.10.1" 26 | source_ip_address = "10.10.10.2" 27 | destination_port = "22" 28 | enabled = "true" 29 | } 30 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/hard-coded-secrets/encryption-key-in-plaintext.tf: -------------------------------------------------------------------------------- 1 | resource "google_compute_disk" "good_example" { 2 | disk_encryption_key { 3 | raw_key = "b2ggbm8gdGhpcyBpcyBiYWQ=" 4 | kms_key_self_link = google_kms_crypto_key.my_crypto_key.id 5 | } 6 | } 7 | 8 | resource "google_compute_disk" "good_example" { 9 | disk_encryption_key { 10 | kms_key_self_link = google_kms_crypto_key.my_crypto_key.id 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/hard-coded-secrets/plaintext-password.tf: -------------------------------------------------------------------------------- 1 | resource "openstack_compute_instance_v2" "bad_example" { 2 | admin_pass = "N0tSoS3cretP4ssw0rd" 3 | } 4 | 5 | resource "openstack_compute_instance_v2" "good_example" { 6 | key_pair = "my_key_pair_name" 7 | } 8 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/hard-coded-secrets/plaintext-value-github-actions.tf: -------------------------------------------------------------------------------- 1 | resource "github_actions_environment_secret" "bad_example" { 2 | repository = "my repository name" 3 | environment = "my environment" 4 | secret_name = "my secret name" 5 | plaintext_value = "sensitive secret string" 6 | } 7 | 8 | resource "github_actions_environment_secret" "good_example" { 9 | repository = "my repository name" 10 | environment = "my environment" 11 | secret_name = "my secret name" 12 | encrypted_value = var.some_encrypted_secret_string 13 | } 14 | -------------------------------------------------------------------------------- /glitch/tests/security/terraform/files/hard-coded-secrets/sensitive-credentials-in-vm-custom-data.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_virtual_machine" "bad_example" { 2 | os_profile { 3 | custom_data =<"] 6 | license = "GPL-3.0" 7 | readme = "README.md" 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.10" 11 | "ruamel.yaml" = "0.17.21" 12 | ply = "3.11" 13 | click = "8.1.7" 14 | prettytable = "3.6.0" 15 | pandas = "1.5.3" 16 | configparser = "5.3.0" 17 | puppetparser = "0.2.4" 18 | Jinja2 = "3.1.2" 19 | glitch-python-hcl2 = "0.1.4" 20 | dockerfile-parse = "2.0.0" 21 | bashlex = "0.18" 22 | requests = "^2.31.0" 23 | z3-solver = "^4.12.4.0" 24 | nltk = "^3.8.1" 25 | jsonschema = "^4.21.1" 26 | setuptools = "^69.5.1" 27 | tqdm = "^4.66.2" 28 | 29 | [tool.poetry.group.dev.dependencies] 30 | pytest = "7.3.1" 31 | 32 | [tool.poetry.scripts] 33 | glitch = "glitch.__main__:main" 34 | 35 | [build-system] 36 | requires = ["poetry-core"] 37 | build-backend = "poetry.core.masonry.api" 38 | 39 | [tool.pyright] 40 | typeCheckingMode = "strict" 41 | stubPath = "stubs" 42 | exclude = ["glitch/tests", ".venv", "scripts/"] -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | # Helper Scripts 2 | In this folder we find scripts used for the extraction of data necessary for two code smells: 3 | - Uso of non-official images 4 | - Use of obsolete/deprecated commands or functions 5 | 6 | ### Requirements 7 | The requirements to run these scripts are in the requirements.txt folder. \ 8 | To install them run: 9 | ```shell 10 | pip install -r requirements.txt 11 | ``` 12 | 13 | ### Use of non-official images 14 | This code smell requires a list of official Docker images, this list can be generated 15 | with `docker_images_scraper.py`, this script uses the docker hub API to fetch the official 16 | images and generate a text file with an image per line. 17 | 18 | ### Use of obsolete/deprecated commands or functions 19 | This code smell requires a list of deprecated/obsolete commands and functions, this list can be 20 | generated with `obsolete_commands_scraper.py`, this script scrapes the book 21 | [Unix in a nutshell](https://docstore.mik.ua/orelly/unix3/unixnut/appb_02.htm) which contains a chapter with 22 | deprecated commands. -------------------------------------------------------------------------------- /scripts/docker_images_scraper.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | next_url = "https://hub.docker.com/api/content/v1/products/search?image_filter=official&page=1&page_size=100&q=&type=image" 4 | headers = {"Accept": "application/json", "Search-Version": "v3"} 5 | 6 | images_list = [] 7 | 8 | while next_url: 9 | res = requests.get(next_url, headers=headers).json() 10 | next_url = res["next"] 11 | images = [i["name"] for i in res["summaries"]] 12 | images_list += images 13 | 14 | with open("official_images", "w") as f: 15 | f.write("\n".join(images_list)) 16 | -------------------------------------------------------------------------------- /scripts/obsolete_commads_scraper.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup 3 | 4 | URL = "https://docstore.mik.ua/orelly/unix3/unixnut/appb_02.htm" 5 | page = requests.get(URL) 6 | 7 | soup = BeautifulSoup(page.content, "html.parser") 8 | table = soup.find("table", cellpadding="5", border="1") 9 | tds = table.find_all("td", valign="top") 10 | obsolete = [td.text for td in tds if len(td) == 1] 11 | 12 | with open("obsolete_commands", "w") as f: 13 | f.write("\n".join(obsolete)) 14 | -------------------------------------------------------------------------------- /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4==4.11.2 ; python_version >= "3.10" and python_version < "4.0" 2 | certifi==2023.11.17 ; python_version >= "3.10" and python_version < "4" 3 | charset-normalizer==3.0.1 ; python_version >= "3.10" and python_version < "4" 4 | idna==3.4 ; python_version >= "3.10" and python_version < "4" 5 | requests==2.31.0 ; python_version >= "3.10" and python_version < "4" 6 | soupsieve==2.3.2.post1 ; python_version >= "3.10" and python_version < "4.0" 7 | urllib3==2.1.0 ; python_version >= "3.10" and python_version < "4" 8 | -------------------------------------------------------------------------------- /stubs/ply/lex.pyi: -------------------------------------------------------------------------------- 1 | import re 2 | from typing import Any 3 | 4 | def lex( 5 | module: Any = None, 6 | object: Any = None, 7 | debug: bool = False, 8 | optimize: bool = False, 9 | lextab: str = "lextab", 10 | reflags: int = int(re.VERBOSE), 11 | nowarn: bool = False, 12 | outputdir: str | None = None, 13 | debuglog: str | None = None, 14 | errorlog: str | None = None, 15 | ) -> Any: ... 16 | 17 | class Lexer: 18 | lineno: int 19 | 20 | def begin(self, state: str) -> None: ... 21 | def skip(self, n: int) -> None: ... 22 | 23 | class LexToken: 24 | value: str 25 | lexer: Lexer 26 | lexpos: int 27 | type: str 28 | -------------------------------------------------------------------------------- /stubs/ply/yacc.pyi: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | def yacc( 4 | method: str = "LALR", 5 | debug: bool = True, 6 | module: Any = None, 7 | tabmodule: str = "parsetab", 8 | start: Any = None, 9 | check_recursion: bool = True, 10 | optimize: bool = False, 11 | write_tables: bool = True, 12 | debugfile: str = "parser.out", 13 | outputdir: str | None = None, 14 | debuglog: str | None = None, 15 | errorlog: str | None = None, 16 | picklefile: str | None = None, 17 | ) -> Any: ... 18 | 19 | class YaccProduction: 20 | value: str 21 | 22 | def __getitem__(self, n: int) -> Any: ... 23 | def __setitem__(self, n: int, v: Any) -> Any: ... 24 | def lineno(self, n: int) -> int: ... 25 | def lexpos(self, n: int) -> int: ... 26 | def set_lineno(self, n: int, lineno: int) -> None: ... 27 | -------------------------------------------------------------------------------- /stubs/ruamel/__init__.pyi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/stubs/ruamel/__init__.pyi -------------------------------------------------------------------------------- /stubs/ruamel/yaml/__init__.pyi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/stubs/ruamel/yaml/__init__.pyi -------------------------------------------------------------------------------- /stubs/ruamel/yaml/error.pyi: -------------------------------------------------------------------------------- 1 | class StreamMark: 2 | line: int 3 | column: int 4 | -------------------------------------------------------------------------------- /stubs/ruamel/yaml/main.pyi: -------------------------------------------------------------------------------- 1 | from ruamel.yaml.nodes import Node 2 | from typing import TextIO 3 | 4 | class YAML: 5 | def compose(self, stream: str | TextIO) -> Node | None: ... 6 | -------------------------------------------------------------------------------- /stubs/ruamel/yaml/nodes.pyi: -------------------------------------------------------------------------------- 1 | from ruamel.yaml.tokens import Token 2 | from typing import List, Union, Optional, Any 3 | from ruamel.yaml.error import StreamMark 4 | 5 | RecursiveTokenList = List[Union[Token, "RecursiveTokenList", None]] 6 | 7 | class Node: 8 | comment: Optional[RecursiveTokenList] 9 | value: Any 10 | start_mark: StreamMark 11 | end_mark: StreamMark 12 | 13 | class ScalarNode(Node): ... 14 | class MappingNode(Node): ... 15 | class SequenceNode(Node): ... 16 | class CollectionNode(Node): ... 17 | -------------------------------------------------------------------------------- /stubs/ruamel/yaml/tokens.pyi: -------------------------------------------------------------------------------- 1 | from ruamel.yaml.error import StreamMark 2 | 3 | class Token: 4 | start_mark: StreamMark 5 | end_mark: StreamMark 6 | 7 | @property 8 | def column(self) -> int: ... 9 | 10 | class CommentToken(Token): 11 | value: str 12 | -------------------------------------------------------------------------------- /vscode-extension/glitch/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "ecmaVersion": 6, 6 | "sourceType": "module" 7 | }, 8 | "plugins": [ 9 | "@typescript-eslint" 10 | ], 11 | "rules": { 12 | "@typescript-eslint/naming-convention": "warn", 13 | "@typescript-eslint/semi": "warn", 14 | "curly": "warn", 15 | "eqeqeq": "warn", 16 | "no-throw-literal": "warn", 17 | "semi": "off" 18 | }, 19 | "ignorePatterns": [ 20 | "out", 21 | "dist", 22 | "**/*.d.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /vscode-extension/glitch/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | dist 3 | node_modules 4 | .vscode-test/ 5 | *.vsix -------------------------------------------------------------------------------- /vscode-extension/glitch/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /vscode-extension/glitch/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ], 15 | "outFiles": [ 16 | "${workspaceFolder}/out/**/*.js" 17 | ], 18 | "preLaunchTask": "${defaultBuildTask}" 19 | }, 20 | { 21 | "name": "Extension Tests", 22 | "type": "extensionHost", 23 | "request": "launch", 24 | "args": [ 25 | "--extensionDevelopmentPath=${workspaceFolder}", 26 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index" 27 | ], 28 | "outFiles": [ 29 | "${workspaceFolder}/out/test/**/*.js" 30 | ], 31 | "preLaunchTask": "${defaultBuildTask}" 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /vscode-extension/glitch/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false // set this to true to hide the "out" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "out": true // set this to false to include "out" folder in search results 8 | }, 9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 10 | "typescript.tsc.autoDetect": "off" 11 | } -------------------------------------------------------------------------------- /vscode-extension/glitch/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /vscode-extension/glitch/.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | src/** 4 | .gitignore 5 | .yarnrc 6 | vsc-extension-quickstart.md 7 | **/tsconfig.json 8 | **/.eslintrc.json 9 | **/*.map 10 | **/*.ts 11 | -------------------------------------------------------------------------------- /vscode-extension/glitch/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to the "glitch" extension will be documented in this file. 4 | 5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 6 | 7 | ## [Unreleased] 8 | 9 | - Initial release -------------------------------------------------------------------------------- /vscode-extension/glitch/images/feature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/vscode-extension/glitch/images/feature.png -------------------------------------------------------------------------------- /vscode-extension/glitch/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sr-lab/GLITCH/8d3b6bbd15d7c96325fe26fd0fd02dcff179fcc5/vscode-extension/glitch/images/logo.png -------------------------------------------------------------------------------- /vscode-extension/glitch/src/extension.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import { subscribeToDocumentChanges } from './diagnostics'; 3 | 4 | export function activate(context: vscode.ExtensionContext) { 5 | const glitchDiagnostics = vscode.languages.createDiagnosticCollection("glitch"); 6 | context.subscriptions.push(glitchDiagnostics); 7 | subscribeToDocumentChanges(context, glitchDiagnostics); 8 | } -------------------------------------------------------------------------------- /vscode-extension/glitch/src/test/runTest.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | 3 | import { runTests } from '@vscode/test-electron'; 4 | 5 | async function main() { 6 | try { 7 | // The folder containing the Extension Manifest package.json 8 | // Passed to `--extensionDevelopmentPath` 9 | const extensionDevelopmentPath = path.resolve(__dirname, '../../'); 10 | 11 | // The path to test runner 12 | // Passed to --extensionTestsPath 13 | const extensionTestsPath = path.resolve(__dirname, './suite/index'); 14 | 15 | // Download VS Code, unzip it and run the integration test 16 | await runTests({ extensionDevelopmentPath, extensionTestsPath }); 17 | } catch (err) { 18 | console.error('Failed to run tests'); 19 | process.exit(1); 20 | } 21 | } 22 | 23 | main(); 24 | -------------------------------------------------------------------------------- /vscode-extension/glitch/src/test/suite/extension.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | 3 | // You can import and use all API from the 'vscode' module 4 | // as well as import your extension to test it 5 | import * as vscode from 'vscode'; 6 | // import * as myExtension from '../../extension'; 7 | 8 | suite('Extension Test Suite', () => { 9 | vscode.window.showInformationMessage('Start all tests.'); 10 | 11 | test('Sample test', () => { 12 | assert.strictEqual(-1, [1, 2, 3].indexOf(5)); 13 | assert.strictEqual(-1, [1, 2, 3].indexOf(0)); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /vscode-extension/glitch/src/test/suite/index.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as Mocha from 'mocha'; 3 | import * as glob from 'glob'; 4 | 5 | export function run(): Promise { 6 | // Create the mocha test 7 | const mocha = new Mocha({ 8 | ui: 'tdd', 9 | color: true 10 | }); 11 | 12 | const testsRoot = path.resolve(__dirname, '..'); 13 | 14 | return new Promise((c, e) => { 15 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { 16 | if (err) { 17 | return e(err); 18 | } 19 | 20 | // Add files to the test suite 21 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); 22 | 23 | try { 24 | // Run the mocha test 25 | mocha.run(failures => { 26 | if (failures > 0) { 27 | e(new Error(`${failures} tests failed.`)); 28 | } else { 29 | c(); 30 | } 31 | }); 32 | } catch (err) { 33 | console.error(err); 34 | e(err); 35 | } 36 | }); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /vscode-extension/glitch/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2020", 5 | "outDir": "out", 6 | "lib": [ 7 | "ES2020" 8 | ], 9 | "sourceMap": true, 10 | "rootDir": "src", 11 | "strict": true /* enable all strict type-checking options */ 12 | /* Additional Checks */ 13 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 14 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 15 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 16 | } 17 | } 18 | --------------------------------------------------------------------------------