paasta-tools 1.21.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- k8s_itests/__init__.py +0 -0
- k8s_itests/test_autoscaling.py +23 -0
- k8s_itests/utils.py +38 -0
- paasta_tools/__init__.py +20 -0
- paasta_tools/adhoc_tools.py +142 -0
- paasta_tools/api/__init__.py +13 -0
- paasta_tools/api/api.py +330 -0
- paasta_tools/api/api_docs/swagger.json +2323 -0
- paasta_tools/api/client.py +106 -0
- paasta_tools/api/settings.py +33 -0
- paasta_tools/api/tweens/__init__.py +6 -0
- paasta_tools/api/tweens/auth.py +125 -0
- paasta_tools/api/tweens/profiling.py +108 -0
- paasta_tools/api/tweens/request_logger.py +124 -0
- paasta_tools/api/views/__init__.py +13 -0
- paasta_tools/api/views/autoscaler.py +100 -0
- paasta_tools/api/views/exception.py +45 -0
- paasta_tools/api/views/flink.py +73 -0
- paasta_tools/api/views/instance.py +395 -0
- paasta_tools/api/views/pause_autoscaler.py +71 -0
- paasta_tools/api/views/remote_run.py +113 -0
- paasta_tools/api/views/resources.py +76 -0
- paasta_tools/api/views/service.py +35 -0
- paasta_tools/api/views/version.py +25 -0
- paasta_tools/apply_external_resources.py +79 -0
- paasta_tools/async_utils.py +109 -0
- paasta_tools/autoscaling/__init__.py +0 -0
- paasta_tools/autoscaling/autoscaling_service_lib.py +57 -0
- paasta_tools/autoscaling/forecasting.py +106 -0
- paasta_tools/autoscaling/max_all_k8s_services.py +41 -0
- paasta_tools/autoscaling/pause_service_autoscaler.py +77 -0
- paasta_tools/autoscaling/utils.py +52 -0
- paasta_tools/bounce_lib.py +184 -0
- paasta_tools/broadcast_log_to_services.py +62 -0
- paasta_tools/cassandracluster_tools.py +210 -0
- paasta_tools/check_autoscaler_max_instances.py +212 -0
- paasta_tools/check_cassandracluster_services_replication.py +35 -0
- paasta_tools/check_flink_services_health.py +203 -0
- paasta_tools/check_kubernetes_api.py +57 -0
- paasta_tools/check_kubernetes_services_replication.py +141 -0
- paasta_tools/check_oom_events.py +244 -0
- paasta_tools/check_services_replication_tools.py +324 -0
- paasta_tools/check_spark_jobs.py +234 -0
- paasta_tools/cleanup_kubernetes_cr.py +138 -0
- paasta_tools/cleanup_kubernetes_crd.py +145 -0
- paasta_tools/cleanup_kubernetes_jobs.py +344 -0
- paasta_tools/cleanup_tron_namespaces.py +96 -0
- paasta_tools/cli/__init__.py +13 -0
- paasta_tools/cli/authentication.py +85 -0
- paasta_tools/cli/cli.py +260 -0
- paasta_tools/cli/cmds/__init__.py +13 -0
- paasta_tools/cli/cmds/autoscale.py +143 -0
- paasta_tools/cli/cmds/check.py +334 -0
- paasta_tools/cli/cmds/cook_image.py +147 -0
- paasta_tools/cli/cmds/get_docker_image.py +76 -0
- paasta_tools/cli/cmds/get_image_version.py +172 -0
- paasta_tools/cli/cmds/get_latest_deployment.py +93 -0
- paasta_tools/cli/cmds/info.py +155 -0
- paasta_tools/cli/cmds/itest.py +117 -0
- paasta_tools/cli/cmds/list.py +66 -0
- paasta_tools/cli/cmds/list_clusters.py +42 -0
- paasta_tools/cli/cmds/list_deploy_queue.py +171 -0
- paasta_tools/cli/cmds/list_namespaces.py +84 -0
- paasta_tools/cli/cmds/local_run.py +1396 -0
- paasta_tools/cli/cmds/logs.py +1601 -0
- paasta_tools/cli/cmds/mark_for_deployment.py +1988 -0
- paasta_tools/cli/cmds/mesh_status.py +174 -0
- paasta_tools/cli/cmds/pause_service_autoscaler.py +107 -0
- paasta_tools/cli/cmds/push_to_registry.py +275 -0
- paasta_tools/cli/cmds/remote_run.py +252 -0
- paasta_tools/cli/cmds/rollback.py +347 -0
- paasta_tools/cli/cmds/secret.py +549 -0
- paasta_tools/cli/cmds/security_check.py +59 -0
- paasta_tools/cli/cmds/spark_run.py +1400 -0
- paasta_tools/cli/cmds/start_stop_restart.py +401 -0
- paasta_tools/cli/cmds/status.py +2302 -0
- paasta_tools/cli/cmds/validate.py +1012 -0
- paasta_tools/cli/cmds/wait_for_deployment.py +275 -0
- paasta_tools/cli/fsm/__init__.py +13 -0
- paasta_tools/cli/fsm/autosuggest.py +82 -0
- paasta_tools/cli/fsm/template/README.md +8 -0
- paasta_tools/cli/fsm/template/cookiecutter.json +7 -0
- paasta_tools/cli/fsm/template/{{cookiecutter.service}}/kubernetes-PROD.yaml +91 -0
- paasta_tools/cli/fsm/template/{{cookiecutter.service}}/monitoring.yaml +20 -0
- paasta_tools/cli/fsm/template/{{cookiecutter.service}}/service.yaml +8 -0
- paasta_tools/cli/fsm/template/{{cookiecutter.service}}/smartstack.yaml +6 -0
- paasta_tools/cli/fsm_cmd.py +121 -0
- paasta_tools/cli/paasta_tabcomplete.sh +23 -0
- paasta_tools/cli/schemas/adhoc_schema.json +199 -0
- paasta_tools/cli/schemas/autoscaling_schema.json +91 -0
- paasta_tools/cli/schemas/autotuned_defaults/cassandracluster_schema.json +37 -0
- paasta_tools/cli/schemas/autotuned_defaults/kubernetes_schema.json +89 -0
- paasta_tools/cli/schemas/deploy_schema.json +173 -0
- paasta_tools/cli/schemas/eks_schema.json +970 -0
- paasta_tools/cli/schemas/kubernetes_schema.json +970 -0
- paasta_tools/cli/schemas/rollback_schema.json +160 -0
- paasta_tools/cli/schemas/service_schema.json +25 -0
- paasta_tools/cli/schemas/smartstack_schema.json +322 -0
- paasta_tools/cli/schemas/tron_schema.json +699 -0
- paasta_tools/cli/utils.py +1118 -0
- paasta_tools/clusterman.py +21 -0
- paasta_tools/config_utils.py +385 -0
- paasta_tools/contrib/__init__.py +0 -0
- paasta_tools/contrib/bounce_log_latency_parser.py +68 -0
- paasta_tools/contrib/check_manual_oapi_changes.sh +24 -0
- paasta_tools/contrib/check_orphans.py +306 -0
- paasta_tools/contrib/create_dynamodb_table.py +35 -0
- paasta_tools/contrib/create_paasta_playground.py +105 -0
- paasta_tools/contrib/emit_allocated_cpu_metrics.py +50 -0
- paasta_tools/contrib/get_running_task_allocation.py +346 -0
- paasta_tools/contrib/habitat_fixer.py +86 -0
- paasta_tools/contrib/ide_helper.py +316 -0
- paasta_tools/contrib/is_pod_healthy_in_proxy.py +139 -0
- paasta_tools/contrib/is_pod_healthy_in_smartstack.py +50 -0
- paasta_tools/contrib/kill_bad_containers.py +109 -0
- paasta_tools/contrib/mass-deploy-tag.sh +44 -0
- paasta_tools/contrib/mock_patch_checker.py +86 -0
- paasta_tools/contrib/paasta_update_soa_memcpu.py +520 -0
- paasta_tools/contrib/render_template.py +129 -0
- paasta_tools/contrib/rightsizer_soaconfigs_update.py +348 -0
- paasta_tools/contrib/service_shard_remove.py +157 -0
- paasta_tools/contrib/service_shard_update.py +373 -0
- paasta_tools/contrib/shared_ip_check.py +77 -0
- paasta_tools/contrib/timeouts_metrics_prom.py +64 -0
- paasta_tools/delete_kubernetes_deployments.py +89 -0
- paasta_tools/deployment_utils.py +44 -0
- paasta_tools/docker_wrapper.py +234 -0
- paasta_tools/docker_wrapper_imports.py +13 -0
- paasta_tools/drain_lib.py +351 -0
- paasta_tools/dump_locally_running_services.py +71 -0
- paasta_tools/eks_tools.py +119 -0
- paasta_tools/envoy_tools.py +373 -0
- paasta_tools/firewall.py +504 -0
- paasta_tools/firewall_logging.py +154 -0
- paasta_tools/firewall_update.py +172 -0
- paasta_tools/flink_tools.py +345 -0
- paasta_tools/flinkeks_tools.py +90 -0
- paasta_tools/frameworks/__init__.py +0 -0
- paasta_tools/frameworks/adhoc_scheduler.py +71 -0
- paasta_tools/frameworks/constraints.py +87 -0
- paasta_tools/frameworks/native_scheduler.py +652 -0
- paasta_tools/frameworks/native_service_config.py +301 -0
- paasta_tools/frameworks/task_store.py +245 -0
- paasta_tools/generate_all_deployments +9 -0
- paasta_tools/generate_authenticating_services.py +94 -0
- paasta_tools/generate_deployments_for_service.py +255 -0
- paasta_tools/generate_services_file.py +114 -0
- paasta_tools/generate_services_yaml.py +30 -0
- paasta_tools/hacheck.py +76 -0
- paasta_tools/instance/__init__.py +0 -0
- paasta_tools/instance/hpa_metrics_parser.py +122 -0
- paasta_tools/instance/kubernetes.py +1362 -0
- paasta_tools/iptables.py +240 -0
- paasta_tools/kafkacluster_tools.py +143 -0
- paasta_tools/kubernetes/__init__.py +0 -0
- paasta_tools/kubernetes/application/__init__.py +0 -0
- paasta_tools/kubernetes/application/controller_wrappers.py +476 -0
- paasta_tools/kubernetes/application/tools.py +90 -0
- paasta_tools/kubernetes/bin/__init__.py +0 -0
- paasta_tools/kubernetes/bin/kubernetes_remove_evicted_pods.py +164 -0
- paasta_tools/kubernetes/bin/paasta_cleanup_remote_run_resources.py +135 -0
- paasta_tools/kubernetes/bin/paasta_cleanup_stale_nodes.py +181 -0
- paasta_tools/kubernetes/bin/paasta_secrets_sync.py +758 -0
- paasta_tools/kubernetes/remote_run.py +558 -0
- paasta_tools/kubernetes_tools.py +4679 -0
- paasta_tools/list_kubernetes_service_instances.py +128 -0
- paasta_tools/list_tron_namespaces.py +60 -0
- paasta_tools/long_running_service_tools.py +678 -0
- paasta_tools/mac_address.py +44 -0
- paasta_tools/marathon_dashboard.py +0 -0
- paasta_tools/mesos/__init__.py +0 -0
- paasta_tools/mesos/cfg.py +46 -0
- paasta_tools/mesos/cluster.py +60 -0
- paasta_tools/mesos/exceptions.py +59 -0
- paasta_tools/mesos/framework.py +77 -0
- paasta_tools/mesos/log.py +48 -0
- paasta_tools/mesos/master.py +306 -0
- paasta_tools/mesos/mesos_file.py +169 -0
- paasta_tools/mesos/parallel.py +52 -0
- paasta_tools/mesos/slave.py +115 -0
- paasta_tools/mesos/task.py +94 -0
- paasta_tools/mesos/util.py +69 -0
- paasta_tools/mesos/zookeeper.py +37 -0
- paasta_tools/mesos_maintenance.py +848 -0
- paasta_tools/mesos_tools.py +1051 -0
- paasta_tools/metrics/__init__.py +0 -0
- paasta_tools/metrics/metastatus_lib.py +1110 -0
- paasta_tools/metrics/metrics_lib.py +217 -0
- paasta_tools/monitoring/__init__.py +13 -0
- paasta_tools/monitoring/check_k8s_api_performance.py +110 -0
- paasta_tools/monitoring_tools.py +652 -0
- paasta_tools/monkrelaycluster_tools.py +146 -0
- paasta_tools/nrtsearchservice_tools.py +143 -0
- paasta_tools/nrtsearchserviceeks_tools.py +68 -0
- paasta_tools/oom_logger.py +321 -0
- paasta_tools/paasta_deploy_tron_jobs +3 -0
- paasta_tools/paasta_execute_docker_command.py +123 -0
- paasta_tools/paasta_native_serviceinit.py +21 -0
- paasta_tools/paasta_service_config_loader.py +201 -0
- paasta_tools/paastaapi/__init__.py +29 -0
- paasta_tools/paastaapi/api/__init__.py +3 -0
- paasta_tools/paastaapi/api/autoscaler_api.py +302 -0
- paasta_tools/paastaapi/api/default_api.py +569 -0
- paasta_tools/paastaapi/api/remote_run_api.py +604 -0
- paasta_tools/paastaapi/api/resources_api.py +157 -0
- paasta_tools/paastaapi/api/service_api.py +1736 -0
- paasta_tools/paastaapi/api_client.py +818 -0
- paasta_tools/paastaapi/apis/__init__.py +22 -0
- paasta_tools/paastaapi/configuration.py +455 -0
- paasta_tools/paastaapi/exceptions.py +137 -0
- paasta_tools/paastaapi/model/__init__.py +5 -0
- paasta_tools/paastaapi/model/adhoc_launch_history.py +176 -0
- paasta_tools/paastaapi/model/autoscaler_count_msg.py +176 -0
- paasta_tools/paastaapi/model/deploy_queue.py +178 -0
- paasta_tools/paastaapi/model/deploy_queue_service_instance.py +194 -0
- paasta_tools/paastaapi/model/envoy_backend.py +185 -0
- paasta_tools/paastaapi/model/envoy_location.py +184 -0
- paasta_tools/paastaapi/model/envoy_status.py +181 -0
- paasta_tools/paastaapi/model/flink_cluster_overview.py +188 -0
- paasta_tools/paastaapi/model/flink_config.py +173 -0
- paasta_tools/paastaapi/model/flink_job.py +186 -0
- paasta_tools/paastaapi/model/flink_job_details.py +192 -0
- paasta_tools/paastaapi/model/flink_jobs.py +175 -0
- paasta_tools/paastaapi/model/float_and_error.py +173 -0
- paasta_tools/paastaapi/model/hpa_metric.py +176 -0
- paasta_tools/paastaapi/model/inline_object.py +170 -0
- paasta_tools/paastaapi/model/inline_response200.py +170 -0
- paasta_tools/paastaapi/model/inline_response2001.py +170 -0
- paasta_tools/paastaapi/model/instance_bounce_status.py +200 -0
- paasta_tools/paastaapi/model/instance_mesh_status.py +186 -0
- paasta_tools/paastaapi/model/instance_status.py +220 -0
- paasta_tools/paastaapi/model/instance_status_adhoc.py +187 -0
- paasta_tools/paastaapi/model/instance_status_cassandracluster.py +173 -0
- paasta_tools/paastaapi/model/instance_status_flink.py +173 -0
- paasta_tools/paastaapi/model/instance_status_kafkacluster.py +173 -0
- paasta_tools/paastaapi/model/instance_status_kubernetes.py +263 -0
- paasta_tools/paastaapi/model/instance_status_kubernetes_autoscaling_status.py +187 -0
- paasta_tools/paastaapi/model/instance_status_kubernetes_v2.py +197 -0
- paasta_tools/paastaapi/model/instance_status_tron.py +204 -0
- paasta_tools/paastaapi/model/instance_tasks.py +182 -0
- paasta_tools/paastaapi/model/integer_and_error.py +173 -0
- paasta_tools/paastaapi/model/kubernetes_container.py +178 -0
- paasta_tools/paastaapi/model/kubernetes_container_v2.py +219 -0
- paasta_tools/paastaapi/model/kubernetes_healthcheck.py +176 -0
- paasta_tools/paastaapi/model/kubernetes_pod.py +201 -0
- paasta_tools/paastaapi/model/kubernetes_pod_event.py +176 -0
- paasta_tools/paastaapi/model/kubernetes_pod_v2.py +213 -0
- paasta_tools/paastaapi/model/kubernetes_replica_set.py +185 -0
- paasta_tools/paastaapi/model/kubernetes_version.py +202 -0
- paasta_tools/paastaapi/model/remote_run_outcome.py +189 -0
- paasta_tools/paastaapi/model/remote_run_start.py +185 -0
- paasta_tools/paastaapi/model/remote_run_stop.py +176 -0
- paasta_tools/paastaapi/model/remote_run_token.py +173 -0
- paasta_tools/paastaapi/model/resource.py +187 -0
- paasta_tools/paastaapi/model/resource_item.py +187 -0
- paasta_tools/paastaapi/model/resource_value.py +176 -0
- paasta_tools/paastaapi/model/smartstack_backend.py +191 -0
- paasta_tools/paastaapi/model/smartstack_location.py +181 -0
- paasta_tools/paastaapi/model/smartstack_status.py +181 -0
- paasta_tools/paastaapi/model/task_tail_lines.py +176 -0
- paasta_tools/paastaapi/model_utils.py +1879 -0
- paasta_tools/paastaapi/models/__init__.py +62 -0
- paasta_tools/paastaapi/rest.py +287 -0
- paasta_tools/prune_completed_pods.py +220 -0
- paasta_tools/puppet_service_tools.py +59 -0
- paasta_tools/py.typed +1 -0
- paasta_tools/remote_git.py +127 -0
- paasta_tools/run-paasta-api-in-dev-mode.py +57 -0
- paasta_tools/run-paasta-api-playground.py +51 -0
- paasta_tools/secret_providers/__init__.py +66 -0
- paasta_tools/secret_providers/vault.py +214 -0
- paasta_tools/secret_tools.py +277 -0
- paasta_tools/setup_istio_mesh.py +353 -0
- paasta_tools/setup_kubernetes_cr.py +412 -0
- paasta_tools/setup_kubernetes_crd.py +138 -0
- paasta_tools/setup_kubernetes_internal_crd.py +154 -0
- paasta_tools/setup_kubernetes_job.py +353 -0
- paasta_tools/setup_prometheus_adapter_config.py +1028 -0
- paasta_tools/setup_tron_namespace.py +248 -0
- paasta_tools/slack.py +75 -0
- paasta_tools/smartstack_tools.py +676 -0
- paasta_tools/spark_tools.py +283 -0
- paasta_tools/synapse_srv_namespaces_fact.py +42 -0
- paasta_tools/tron/__init__.py +0 -0
- paasta_tools/tron/client.py +158 -0
- paasta_tools/tron/tron_command_context.py +194 -0
- paasta_tools/tron/tron_timeutils.py +101 -0
- paasta_tools/tron_tools.py +1448 -0
- paasta_tools/utils.py +4307 -0
- paasta_tools/yaml_tools.py +44 -0
- paasta_tools-1.21.3.data/scripts/apply_external_resources.py +79 -0
- paasta_tools-1.21.3.data/scripts/bounce_log_latency_parser.py +68 -0
- paasta_tools-1.21.3.data/scripts/check_autoscaler_max_instances.py +212 -0
- paasta_tools-1.21.3.data/scripts/check_cassandracluster_services_replication.py +35 -0
- paasta_tools-1.21.3.data/scripts/check_flink_services_health.py +203 -0
- paasta_tools-1.21.3.data/scripts/check_kubernetes_api.py +57 -0
- paasta_tools-1.21.3.data/scripts/check_kubernetes_services_replication.py +141 -0
- paasta_tools-1.21.3.data/scripts/check_manual_oapi_changes.sh +24 -0
- paasta_tools-1.21.3.data/scripts/check_oom_events.py +244 -0
- paasta_tools-1.21.3.data/scripts/check_orphans.py +306 -0
- paasta_tools-1.21.3.data/scripts/check_spark_jobs.py +234 -0
- paasta_tools-1.21.3.data/scripts/cleanup_kubernetes_cr.py +138 -0
- paasta_tools-1.21.3.data/scripts/cleanup_kubernetes_crd.py +145 -0
- paasta_tools-1.21.3.data/scripts/cleanup_kubernetes_jobs.py +344 -0
- paasta_tools-1.21.3.data/scripts/create_dynamodb_table.py +35 -0
- paasta_tools-1.21.3.data/scripts/create_paasta_playground.py +105 -0
- paasta_tools-1.21.3.data/scripts/delete_kubernetes_deployments.py +89 -0
- paasta_tools-1.21.3.data/scripts/emit_allocated_cpu_metrics.py +50 -0
- paasta_tools-1.21.3.data/scripts/generate_all_deployments +9 -0
- paasta_tools-1.21.3.data/scripts/generate_authenticating_services.py +94 -0
- paasta_tools-1.21.3.data/scripts/generate_deployments_for_service.py +255 -0
- paasta_tools-1.21.3.data/scripts/generate_services_file.py +114 -0
- paasta_tools-1.21.3.data/scripts/generate_services_yaml.py +30 -0
- paasta_tools-1.21.3.data/scripts/get_running_task_allocation.py +346 -0
- paasta_tools-1.21.3.data/scripts/habitat_fixer.py +86 -0
- paasta_tools-1.21.3.data/scripts/ide_helper.py +316 -0
- paasta_tools-1.21.3.data/scripts/is_pod_healthy_in_proxy.py +139 -0
- paasta_tools-1.21.3.data/scripts/is_pod_healthy_in_smartstack.py +50 -0
- paasta_tools-1.21.3.data/scripts/kill_bad_containers.py +109 -0
- paasta_tools-1.21.3.data/scripts/kubernetes_remove_evicted_pods.py +164 -0
- paasta_tools-1.21.3.data/scripts/mass-deploy-tag.sh +44 -0
- paasta_tools-1.21.3.data/scripts/mock_patch_checker.py +86 -0
- paasta_tools-1.21.3.data/scripts/paasta_cleanup_remote_run_resources.py +135 -0
- paasta_tools-1.21.3.data/scripts/paasta_cleanup_stale_nodes.py +181 -0
- paasta_tools-1.21.3.data/scripts/paasta_deploy_tron_jobs +3 -0
- paasta_tools-1.21.3.data/scripts/paasta_execute_docker_command.py +123 -0
- paasta_tools-1.21.3.data/scripts/paasta_secrets_sync.py +758 -0
- paasta_tools-1.21.3.data/scripts/paasta_tabcomplete.sh +23 -0
- paasta_tools-1.21.3.data/scripts/paasta_update_soa_memcpu.py +520 -0
- paasta_tools-1.21.3.data/scripts/render_template.py +129 -0
- paasta_tools-1.21.3.data/scripts/rightsizer_soaconfigs_update.py +348 -0
- paasta_tools-1.21.3.data/scripts/service_shard_remove.py +157 -0
- paasta_tools-1.21.3.data/scripts/service_shard_update.py +373 -0
- paasta_tools-1.21.3.data/scripts/setup_istio_mesh.py +353 -0
- paasta_tools-1.21.3.data/scripts/setup_kubernetes_cr.py +412 -0
- paasta_tools-1.21.3.data/scripts/setup_kubernetes_crd.py +138 -0
- paasta_tools-1.21.3.data/scripts/setup_kubernetes_internal_crd.py +154 -0
- paasta_tools-1.21.3.data/scripts/setup_kubernetes_job.py +353 -0
- paasta_tools-1.21.3.data/scripts/setup_prometheus_adapter_config.py +1028 -0
- paasta_tools-1.21.3.data/scripts/shared_ip_check.py +77 -0
- paasta_tools-1.21.3.data/scripts/synapse_srv_namespaces_fact.py +42 -0
- paasta_tools-1.21.3.data/scripts/timeouts_metrics_prom.py +64 -0
- paasta_tools-1.21.3.dist-info/LICENSE +201 -0
- paasta_tools-1.21.3.dist-info/METADATA +74 -0
- paasta_tools-1.21.3.dist-info/RECORD +348 -0
- paasta_tools-1.21.3.dist-info/WHEEL +5 -0
- paasta_tools-1.21.3.dist-info/entry_points.txt +20 -0
- paasta_tools-1.21.3.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# Copyright 2015-2018 Yelp Inc.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
import argparse
|
|
16
|
+
import os
|
|
17
|
+
import re
|
|
18
|
+
import sys
|
|
19
|
+
from typing import Any
|
|
20
|
+
from typing import Dict
|
|
21
|
+
from typing import Optional
|
|
22
|
+
|
|
23
|
+
from service_configuration_lib import DEFAULT_SOA_DIR
|
|
24
|
+
|
|
25
|
+
from paasta_tools.cli.utils import get_instance_config
|
|
26
|
+
from paasta_tools.cli.utils import get_namespaces_for_secret
|
|
27
|
+
from paasta_tools.cli.utils import lazy_choices_completer
|
|
28
|
+
from paasta_tools.cli.utils import list_instances
|
|
29
|
+
from paasta_tools.cli.utils import select_k8s_secret_namespace
|
|
30
|
+
from paasta_tools.kubernetes_tools import get_paasta_secret_name
|
|
31
|
+
from paasta_tools.kubernetes_tools import get_secret
|
|
32
|
+
from paasta_tools.kubernetes_tools import KUBE_CONFIG_USER_PATH
|
|
33
|
+
from paasta_tools.kubernetes_tools import KubeClient
|
|
34
|
+
from paasta_tools.secret_providers import SecretProvider
|
|
35
|
+
from paasta_tools.secret_tools import decrypt_secret_environment_variables
|
|
36
|
+
from paasta_tools.secret_tools import get_secret_provider
|
|
37
|
+
from paasta_tools.secret_tools import SHARED_SECRET_SERVICE
|
|
38
|
+
from paasta_tools.utils import _log_audit
|
|
39
|
+
from paasta_tools.utils import is_secrets_for_teams_enabled
|
|
40
|
+
from paasta_tools.utils import list_clusters
|
|
41
|
+
from paasta_tools.utils import list_services
|
|
42
|
+
from paasta_tools.utils import load_system_paasta_config
|
|
43
|
+
|
|
44
|
+
SECRET_NAME_REGEX = r"([A-Za-z0-9_-]*)"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def check_secret_name(secret_name_arg: str):
|
|
48
|
+
pattern = re.compile(SECRET_NAME_REGEX)
|
|
49
|
+
if (
|
|
50
|
+
not secret_name_arg.startswith("-")
|
|
51
|
+
and not secret_name_arg.startswith("_")
|
|
52
|
+
and "".join(pattern.findall(secret_name_arg)) == secret_name_arg
|
|
53
|
+
):
|
|
54
|
+
return secret_name_arg
|
|
55
|
+
raise argparse.ArgumentTypeError(
|
|
56
|
+
"--secret-name argument should only contain letters, numbers, "
|
|
57
|
+
"dashes and underscores characters and cannot start from latter two"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def add_add_subparser(subparsers):
|
|
62
|
+
secret_parser_add = subparsers.add_parser("add", help="adds a paasta secret")
|
|
63
|
+
_add_common_args(secret_parser_add)
|
|
64
|
+
_add_and_update_args(secret_parser_add)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def add_update_subparser(subparsers):
|
|
68
|
+
secret_parser_update = subparsers.add_parser(
|
|
69
|
+
"update", help="updates a paasta secret"
|
|
70
|
+
)
|
|
71
|
+
_add_common_args(secret_parser_update)
|
|
72
|
+
_add_and_update_args(secret_parser_update)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def add_decrypt_subparser(subparsers):
|
|
76
|
+
secret_parser_decrypt = subparsers.add_parser(
|
|
77
|
+
"decrypt", help="decrypts a single paasta secret"
|
|
78
|
+
)
|
|
79
|
+
_add_common_args(secret_parser_decrypt)
|
|
80
|
+
|
|
81
|
+
secret_parser_decrypt.add_argument(
|
|
82
|
+
"-n",
|
|
83
|
+
"--secret-name",
|
|
84
|
+
type=check_secret_name,
|
|
85
|
+
required=True,
|
|
86
|
+
help="The name of the secret to decrypt, this is the secret filename without the extension.",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
secret_parser_decrypt.add_argument(
|
|
90
|
+
"-c",
|
|
91
|
+
"--clusters",
|
|
92
|
+
required=False,
|
|
93
|
+
type=_validate_single_cluster,
|
|
94
|
+
help=(
|
|
95
|
+
"The cluster to decrypt for, e.g. pnw-prod. "
|
|
96
|
+
"Note: for decrypt only one cluster is allowed. "
|
|
97
|
+
"This argument is required unless the secret is only defined in one cluster."
|
|
98
|
+
),
|
|
99
|
+
).completer = lazy_choices_completer(list_clusters)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _validate_single_cluster(arg: str) -> str:
|
|
103
|
+
if len(arg.split(",")) > 1:
|
|
104
|
+
raise argparse.ArgumentTypeError("can only decrypt from one cluster at a time")
|
|
105
|
+
return arg
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def add_run_subparser(subparsers):
|
|
109
|
+
secret_parser_run = subparsers.add_parser(
|
|
110
|
+
"run",
|
|
111
|
+
help="runs a command with paasta secrets",
|
|
112
|
+
description=(
|
|
113
|
+
"Runs a command with the secret environment variables from "
|
|
114
|
+
"a given service instance. The command is run directly, not "
|
|
115
|
+
"in a Docker container. "
|
|
116
|
+
"Only the environment variables containing secrets are included. "
|
|
117
|
+
"No attempt at redacting secrets appearing in the output is made."
|
|
118
|
+
),
|
|
119
|
+
conflict_handler="resolve",
|
|
120
|
+
)
|
|
121
|
+
_add_common_args(secret_parser_run, allow_shared=False)
|
|
122
|
+
|
|
123
|
+
secret_parser_run.add_argument(
|
|
124
|
+
"-i",
|
|
125
|
+
"--instance",
|
|
126
|
+
help=(
|
|
127
|
+
"Instance of the service to retrieve secret environment variables "
|
|
128
|
+
"for, such as 'main' or 'canary'. Secrets will be selected and "
|
|
129
|
+
"mapped to environment variables based on the configs for the instance."
|
|
130
|
+
),
|
|
131
|
+
required=True,
|
|
132
|
+
).completer = lazy_choices_completer(list_instances)
|
|
133
|
+
|
|
134
|
+
secret_parser_run.add_argument(
|
|
135
|
+
"-c",
|
|
136
|
+
"--clusters",
|
|
137
|
+
required=True,
|
|
138
|
+
type=_validate_single_cluster,
|
|
139
|
+
help=(
|
|
140
|
+
"The cluster to retrieve secrets for, e.g. norcal-devc. "
|
|
141
|
+
"A list of clusters is not supported for this command."
|
|
142
|
+
),
|
|
143
|
+
).completer = lazy_choices_completer(list_clusters)
|
|
144
|
+
|
|
145
|
+
secret_parser_run.add_argument(
|
|
146
|
+
"cmd",
|
|
147
|
+
nargs="*",
|
|
148
|
+
default=["bash"],
|
|
149
|
+
help=(
|
|
150
|
+
"The command to run with the specified PaaSTA secrets. "
|
|
151
|
+
"If not given, starts an interactive bash shell."
|
|
152
|
+
),
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _add_and_update_args(parser: argparse.ArgumentParser):
|
|
157
|
+
"""common args for `add` and `update`."""
|
|
158
|
+
parser.add_argument(
|
|
159
|
+
"-p",
|
|
160
|
+
"--plain-text",
|
|
161
|
+
required=False,
|
|
162
|
+
type=str,
|
|
163
|
+
help="Optionally specify the secret as a command line argument",
|
|
164
|
+
)
|
|
165
|
+
parser.add_argument(
|
|
166
|
+
"-i",
|
|
167
|
+
"--stdin",
|
|
168
|
+
required=False,
|
|
169
|
+
action="store_true",
|
|
170
|
+
default=False,
|
|
171
|
+
help="Optionally pass the plaintext from stdin",
|
|
172
|
+
)
|
|
173
|
+
parser.add_argument(
|
|
174
|
+
"--cross-env-motivation",
|
|
175
|
+
required=False,
|
|
176
|
+
type=str,
|
|
177
|
+
help=(
|
|
178
|
+
"Provide motivation in case the same value is being duplicated "
|
|
179
|
+
"across multiple runtime environments when adding or updating a secret"
|
|
180
|
+
),
|
|
181
|
+
metavar="MOTIVATION",
|
|
182
|
+
)
|
|
183
|
+
parser.add_argument(
|
|
184
|
+
"-n",
|
|
185
|
+
"--secret-name",
|
|
186
|
+
type=check_secret_name,
|
|
187
|
+
required=True,
|
|
188
|
+
help="The name of the secret to create/update, "
|
|
189
|
+
"this is the name you will reference in your "
|
|
190
|
+
"services yaml files and should "
|
|
191
|
+
"be unique per service.",
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
parser.add_argument( # type: ignore
|
|
195
|
+
"-c",
|
|
196
|
+
"--clusters",
|
|
197
|
+
help="A comma-separated list of clusters to create secrets for. "
|
|
198
|
+
"Note: this is translated to ecosystems because Vault is run "
|
|
199
|
+
"at an ecosystem level. As a result you can only have different "
|
|
200
|
+
"secrets per ecosystem. (it is not possible for example to encrypt "
|
|
201
|
+
"a different value for pnw-prod vs nova-prod. "
|
|
202
|
+
"Defaults to all clusters in which the service runs. "
|
|
203
|
+
"For example: --clusters pnw-prod,nova-prod ",
|
|
204
|
+
).completer = lazy_choices_completer(list_clusters)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _add_vault_auth_args(parser: argparse.ArgumentParser):
|
|
208
|
+
parser.add_argument(
|
|
209
|
+
"--vault-auth-method",
|
|
210
|
+
help="Override how we auth with vault, defaults to token if not present",
|
|
211
|
+
type=str,
|
|
212
|
+
dest="vault_auth_method",
|
|
213
|
+
required=False,
|
|
214
|
+
default="token",
|
|
215
|
+
choices=["token", "ldap"],
|
|
216
|
+
)
|
|
217
|
+
parser.add_argument(
|
|
218
|
+
"--vault-token-file",
|
|
219
|
+
help="Override vault token file, defaults to %(default)s",
|
|
220
|
+
type=str,
|
|
221
|
+
dest="vault_token_file",
|
|
222
|
+
required=False,
|
|
223
|
+
default="/var/spool/.paasta_vault_token",
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def _add_common_args(parser: argparse.ArgumentParser, allow_shared: bool = True):
|
|
228
|
+
# available from any subcommand
|
|
229
|
+
parser.add_argument(
|
|
230
|
+
"-y",
|
|
231
|
+
"--yelpsoa-config-root",
|
|
232
|
+
dest="yelpsoa_config_root",
|
|
233
|
+
help="A directory from which yelpsoa-configs should be read from",
|
|
234
|
+
default=DEFAULT_SOA_DIR,
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
_add_vault_auth_args(parser)
|
|
238
|
+
|
|
239
|
+
if allow_shared:
|
|
240
|
+
service_group = parser.add_mutually_exclusive_group(required=True)
|
|
241
|
+
else:
|
|
242
|
+
service_group = parser # type: ignore
|
|
243
|
+
|
|
244
|
+
service_group.add_argument( # type: ignore
|
|
245
|
+
"-s",
|
|
246
|
+
"--service",
|
|
247
|
+
required=not allow_shared,
|
|
248
|
+
help="The name of the service on which you wish to act",
|
|
249
|
+
).completer = lazy_choices_completer(list_services)
|
|
250
|
+
|
|
251
|
+
if allow_shared:
|
|
252
|
+
service_group.add_argument(
|
|
253
|
+
"--shared",
|
|
254
|
+
help="Act on a secret that can be shared by all services",
|
|
255
|
+
action="store_true",
|
|
256
|
+
)
|
|
257
|
+
else:
|
|
258
|
+
service_group.add_argument(
|
|
259
|
+
"--shared",
|
|
260
|
+
action="store_false",
|
|
261
|
+
help=argparse.SUPPRESS,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def add_subparser(subparsers):
|
|
266
|
+
secret_parser = subparsers.add_parser(
|
|
267
|
+
"secret",
|
|
268
|
+
help="Add/update/read PaaSTA service secrets",
|
|
269
|
+
description=(
|
|
270
|
+
"This set of commands allows you to add, update, or read secrets for your services, "
|
|
271
|
+
"configured as environment variables. If adding or updating, it modifies your local "
|
|
272
|
+
"checkout of yelpsoa-configs and you must then commit and "
|
|
273
|
+
"push the changes back to git."
|
|
274
|
+
),
|
|
275
|
+
)
|
|
276
|
+
secret_parser.set_defaults(command=paasta_secret)
|
|
277
|
+
|
|
278
|
+
secret_subparsers = secret_parser.add_subparsers(
|
|
279
|
+
dest="action",
|
|
280
|
+
title="paasta secret subcommands",
|
|
281
|
+
help=(
|
|
282
|
+
"Run paasta secret <SUBCOMMAND> --help for information on per-subcommand arguments. "
|
|
283
|
+
"Not all arguments are available on all subcommands."
|
|
284
|
+
),
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
add_add_subparser(secret_subparsers)
|
|
288
|
+
add_decrypt_subparser(secret_subparsers)
|
|
289
|
+
add_update_subparser(secret_subparsers)
|
|
290
|
+
add_run_subparser(secret_subparsers)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def secret_name_for_env(secret_name):
|
|
294
|
+
secret_name = secret_name.upper()
|
|
295
|
+
valid_parts = re.findall(r"[a-zA-Z0-9_]+", secret_name)
|
|
296
|
+
return "_".join(valid_parts)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def print_paasta_helper(secret_path, secret_name, is_shared):
|
|
300
|
+
print(
|
|
301
|
+
"\nYou have successfully encrypted your new secret and it\n"
|
|
302
|
+
"has been stored at {}\n"
|
|
303
|
+
"To use the secret in a service you can add it to your PaaSTA service\n"
|
|
304
|
+
"as an environment variable.\n"
|
|
305
|
+
"You do so by referencing it in the env dict in your yaml config:\n\n"
|
|
306
|
+
"main:\n"
|
|
307
|
+
" cpus: 1\n"
|
|
308
|
+
" env:\n"
|
|
309
|
+
" PAASTA_SECRET_{}: {}SECRET({})\n\n"
|
|
310
|
+
"Once you have referenced the secret you must commit the newly\n"
|
|
311
|
+
"created/updated json file and your changes to your yaml config. When\n"
|
|
312
|
+
"you push to master PaaSTA will bounce your service and the new\n"
|
|
313
|
+
"secrets plaintext will be in the environment variable you have\n"
|
|
314
|
+
"specified. The PAASTA_SECRET_ prefix is optional but necessary\n"
|
|
315
|
+
"for the yelp_servlib client library".format(
|
|
316
|
+
secret_path,
|
|
317
|
+
secret_name_for_env(secret_name),
|
|
318
|
+
"SHARED_" if is_shared else "",
|
|
319
|
+
secret_name,
|
|
320
|
+
)
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def get_plaintext_input(args):
|
|
325
|
+
if args.stdin:
|
|
326
|
+
plaintext = sys.stdin.buffer.read()
|
|
327
|
+
elif args.plain_text:
|
|
328
|
+
plaintext = args.plain_text.encode("utf-8")
|
|
329
|
+
else:
|
|
330
|
+
print(
|
|
331
|
+
"Please enter the plaintext for the secret, then enter a newline and Ctrl-D when done."
|
|
332
|
+
)
|
|
333
|
+
lines = []
|
|
334
|
+
while True:
|
|
335
|
+
try:
|
|
336
|
+
line = input()
|
|
337
|
+
except EOFError:
|
|
338
|
+
break
|
|
339
|
+
lines.append(line)
|
|
340
|
+
plaintext = "\n".join(lines).encode("utf-8")
|
|
341
|
+
print("The secret as Python bytes is:", repr(plaintext))
|
|
342
|
+
print("Please make sure the value inside the quotes is correct.")
|
|
343
|
+
return plaintext
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def is_service_folder(soa_dir, service_name):
|
|
347
|
+
return os.path.isfile(os.path.join(soa_dir, service_name, "service.yaml"))
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _get_secret_provider_for_service(
|
|
351
|
+
service_name: str,
|
|
352
|
+
cluster_names: Optional[str] = None,
|
|
353
|
+
soa_dir: Optional[str] = None,
|
|
354
|
+
secret_provider_extra_kwargs: Optional[Dict[str, Any]] = None,
|
|
355
|
+
) -> SecretProvider:
|
|
356
|
+
secret_provider_extra_kwargs = secret_provider_extra_kwargs or {}
|
|
357
|
+
soa_dir = soa_dir or os.getcwd()
|
|
358
|
+
|
|
359
|
+
if not is_service_folder(soa_dir, service_name):
|
|
360
|
+
print(
|
|
361
|
+
"{} not found.\n"
|
|
362
|
+
"You must run this tool from the root of your local yelpsoa checkout\n"
|
|
363
|
+
"The tool modifies files in yelpsoa-configs that you must then commit\n"
|
|
364
|
+
"and push back to git.".format(os.path.join(service_name, "service.yaml"))
|
|
365
|
+
)
|
|
366
|
+
sys.exit(1)
|
|
367
|
+
system_paasta_config = load_system_paasta_config()
|
|
368
|
+
secret_provider_kwargs = {
|
|
369
|
+
"vault_cluster_config": system_paasta_config.get_vault_cluster_config(),
|
|
370
|
+
**secret_provider_extra_kwargs,
|
|
371
|
+
}
|
|
372
|
+
clusters = (
|
|
373
|
+
cluster_names.split(",")
|
|
374
|
+
if cluster_names
|
|
375
|
+
else list_clusters(service=service_name, soa_dir=soa_dir)
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
return get_secret_provider(
|
|
379
|
+
secret_provider_name=system_paasta_config.get_secret_provider_name(),
|
|
380
|
+
soa_dir=soa_dir,
|
|
381
|
+
service_name=service_name,
|
|
382
|
+
cluster_names=clusters,
|
|
383
|
+
secret_provider_kwargs=secret_provider_kwargs,
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def paasta_secret(args):
|
|
388
|
+
if args.shared:
|
|
389
|
+
service = SHARED_SECRET_SERVICE
|
|
390
|
+
if not args.clusters:
|
|
391
|
+
print("A list of clusters is required for shared secrets.")
|
|
392
|
+
sys.exit(1)
|
|
393
|
+
else:
|
|
394
|
+
service = args.service
|
|
395
|
+
|
|
396
|
+
# Check if "decrypt" and "secrets_for_teams" first to avoid vault auth
|
|
397
|
+
if args.action == "decrypt" and is_secrets_for_teams_enabled(
|
|
398
|
+
service, args.yelpsoa_config_root
|
|
399
|
+
):
|
|
400
|
+
clusters = (
|
|
401
|
+
args.clusters.split(",")
|
|
402
|
+
if args.clusters
|
|
403
|
+
else list_clusters(service=service, soa_dir=os.getcwd())
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
if len(clusters) > 1 or not clusters:
|
|
407
|
+
print(
|
|
408
|
+
"Can only decrypt for one specified cluster at a time!\nFor example,"
|
|
409
|
+
" try '-c norcal-devc' to decrypt the secret for this service in norcal-devc."
|
|
410
|
+
)
|
|
411
|
+
sys.exit(1)
|
|
412
|
+
|
|
413
|
+
kube_client = KubeClient(config_file=KUBE_CONFIG_USER_PATH, context=clusters[0])
|
|
414
|
+
|
|
415
|
+
secret_to_k8s_mapping = get_namespaces_for_secret(
|
|
416
|
+
service, clusters[0], args.secret_name, args.yelpsoa_config_root
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
namespace = select_k8s_secret_namespace(secret_to_k8s_mapping)
|
|
420
|
+
|
|
421
|
+
if namespace:
|
|
422
|
+
print(
|
|
423
|
+
get_secret(
|
|
424
|
+
kube_client,
|
|
425
|
+
get_paasta_secret_name(namespace, service, args.secret_name),
|
|
426
|
+
key_name=args.secret_name,
|
|
427
|
+
namespace=namespace,
|
|
428
|
+
)
|
|
429
|
+
)
|
|
430
|
+
# fallback to default in case mapping fails
|
|
431
|
+
else:
|
|
432
|
+
print(
|
|
433
|
+
get_secret(
|
|
434
|
+
kube_client,
|
|
435
|
+
get_paasta_secret_name("paasta", service, args.secret_name),
|
|
436
|
+
key_name=args.secret_name,
|
|
437
|
+
namespace="paasta",
|
|
438
|
+
)
|
|
439
|
+
)
|
|
440
|
+
return
|
|
441
|
+
|
|
442
|
+
if args.action in ["add", "update"]:
|
|
443
|
+
plaintext = get_plaintext_input(args)
|
|
444
|
+
if not plaintext:
|
|
445
|
+
print("Warning: Given plaintext is an empty string.")
|
|
446
|
+
secret_provider = _get_secret_provider_for_service(
|
|
447
|
+
service,
|
|
448
|
+
cluster_names=args.clusters,
|
|
449
|
+
# this will only be invoked on a devbox
|
|
450
|
+
# and only in a context where we certainly
|
|
451
|
+
# want to use the working directory rather
|
|
452
|
+
# than whatever the actual soa_dir path is
|
|
453
|
+
# configured as
|
|
454
|
+
soa_dir=os.getcwd(),
|
|
455
|
+
secret_provider_extra_kwargs={
|
|
456
|
+
"vault_token_file": args.vault_token_file,
|
|
457
|
+
# best solution so far is to change the below string to "token",
|
|
458
|
+
# so that token file is picked up from argparse
|
|
459
|
+
"vault_auth_method": "ldap", # must have LDAP to get 2FA push for prod
|
|
460
|
+
},
|
|
461
|
+
)
|
|
462
|
+
secret_provider.write_secret(
|
|
463
|
+
action=args.action,
|
|
464
|
+
secret_name=args.secret_name,
|
|
465
|
+
plaintext=plaintext,
|
|
466
|
+
cross_environment_motivation=args.cross_env_motivation,
|
|
467
|
+
)
|
|
468
|
+
secret_path = os.path.join(
|
|
469
|
+
secret_provider.secret_dir, f"{args.secret_name}.json"
|
|
470
|
+
)
|
|
471
|
+
_log_audit(
|
|
472
|
+
action=f"{args.action}-secret",
|
|
473
|
+
action_details={"secret_name": args.secret_name, "clusters": args.clusters},
|
|
474
|
+
service=service,
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
print_paasta_helper(secret_path, args.secret_name, args.shared)
|
|
478
|
+
elif args.action == "decrypt":
|
|
479
|
+
secret_provider_extra_kwargs = {
|
|
480
|
+
"vault_auth_method": args.vault_auth_method,
|
|
481
|
+
"vault_token_file": args.vault_token_file,
|
|
482
|
+
}
|
|
483
|
+
secret_provider = _get_secret_provider_for_service(
|
|
484
|
+
service,
|
|
485
|
+
cluster_names=args.clusters,
|
|
486
|
+
# `decrypt` does not require the current working directory
|
|
487
|
+
# to be a writeable git checkout of yelpsoa-configs
|
|
488
|
+
soa_dir=args.yelpsoa_config_root,
|
|
489
|
+
secret_provider_extra_kwargs=secret_provider_extra_kwargs,
|
|
490
|
+
)
|
|
491
|
+
print(
|
|
492
|
+
decrypt_secret(
|
|
493
|
+
secret_provider=secret_provider, secret_name=args.secret_name
|
|
494
|
+
),
|
|
495
|
+
end="",
|
|
496
|
+
)
|
|
497
|
+
elif args.action == "run":
|
|
498
|
+
new_environ = os.environ.copy()
|
|
499
|
+
|
|
500
|
+
system_paasta_config = load_system_paasta_config()
|
|
501
|
+
secret_provider_kwargs = {
|
|
502
|
+
"vault_cluster_config": system_paasta_config.get_vault_cluster_config(),
|
|
503
|
+
"vault_auth_method": args.vault_auth_method,
|
|
504
|
+
"vault_token_file": args.vault_token_file,
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
# This includes only the environment variables mapped to secrets,
|
|
508
|
+
# other environment variables are not included.
|
|
509
|
+
# All environment variables set in the current shell will also
|
|
510
|
+
# be passed through.
|
|
511
|
+
new_secret_vars = decrypt_secret_environment_variables(
|
|
512
|
+
secret_provider_name=system_paasta_config.get_secret_provider_name(),
|
|
513
|
+
environment=get_instance_config(
|
|
514
|
+
service=args.service,
|
|
515
|
+
instance=args.instance,
|
|
516
|
+
cluster=args.clusters,
|
|
517
|
+
soa_dir=args.yelpsoa_config_root,
|
|
518
|
+
).get_env(),
|
|
519
|
+
soa_dir=args.yelpsoa_config_root,
|
|
520
|
+
service_name=args.service,
|
|
521
|
+
cluster_name=args.clusters,
|
|
522
|
+
secret_provider_kwargs=secret_provider_kwargs,
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
for var_name, var_value in new_secret_vars.items():
|
|
526
|
+
new_environ[var_name] = var_value
|
|
527
|
+
|
|
528
|
+
if args.cmd == ["bash"]:
|
|
529
|
+
# make it clear that we're running in a sub-shell
|
|
530
|
+
new_environ["PS1"] = r"(paasta secret run) \$ "
|
|
531
|
+
|
|
532
|
+
# This is like subprocess.run but never returns (it replaces the current process),
|
|
533
|
+
# we do this to play nicely with pgctl:
|
|
534
|
+
# https://pgctl.readthedocs.io/en/latest/user/quickstart.html#writing-playground-services
|
|
535
|
+
os.execvpe(args.cmd[0], args.cmd, new_environ)
|
|
536
|
+
else:
|
|
537
|
+
print("Unknown action")
|
|
538
|
+
sys.exit(1)
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
def decrypt_secret(secret_provider, secret_name):
|
|
542
|
+
if len(secret_provider.cluster_names) > 1:
|
|
543
|
+
print(
|
|
544
|
+
"Can only decrypt for one cluster at a time!\nFor example, try '-c norcal-devc'"
|
|
545
|
+
" to decrypt the secret for this service in norcal-devc."
|
|
546
|
+
)
|
|
547
|
+
sys.exit(1)
|
|
548
|
+
|
|
549
|
+
return secret_provider.decrypt_secret(secret_name)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# Copyright 2015-2016 Yelp Inc.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
from paasta_tools.utils import _run
|
|
16
|
+
from paasta_tools.utils import load_system_paasta_config
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def add_subparser(subparsers):
|
|
20
|
+
list_parser = subparsers.add_parser(
|
|
21
|
+
"security-check",
|
|
22
|
+
description="Performs a security check consisting of a few tests.",
|
|
23
|
+
help="Performs a security check",
|
|
24
|
+
)
|
|
25
|
+
list_parser.add_argument(
|
|
26
|
+
"-s",
|
|
27
|
+
"--service",
|
|
28
|
+
help='Name of service for which you wish to check. Leading "services-", as included in a '
|
|
29
|
+
"Jenkins job name, will be stripped.",
|
|
30
|
+
required=True,
|
|
31
|
+
)
|
|
32
|
+
list_parser.add_argument(
|
|
33
|
+
"-c", "--commit", help="Git sha of the image to check", required=True
|
|
34
|
+
)
|
|
35
|
+
list_parser.set_defaults(command=perform_security_check)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def perform_security_check(args):
|
|
39
|
+
"""It runs a few security tests, checks the return code and prints output that should help in fixing failures.
|
|
40
|
+
If you are at Yelp, please visit https://confluence.yelpcorp.com/display/PAASTA/PaaSTA+security-check+explained
|
|
41
|
+
to learn more.
|
|
42
|
+
:param args: service - the name of the service; commit - upstream git commit.
|
|
43
|
+
:return: 0 if the security-check passed, non-zero if it failed.
|
|
44
|
+
"""
|
|
45
|
+
security_check_command = load_system_paasta_config().get_security_check_command()
|
|
46
|
+
if not security_check_command:
|
|
47
|
+
print("Nothing to be executed during the security-check step")
|
|
48
|
+
return 0
|
|
49
|
+
|
|
50
|
+
command = f"{security_check_command} {args.service} {args.commit}"
|
|
51
|
+
|
|
52
|
+
ret_code, output = _run(command, timeout=3600, stream=True)
|
|
53
|
+
if ret_code != 0:
|
|
54
|
+
print(
|
|
55
|
+
"The security-check failed. Please visit y/security-check-runbook to learn how to fix it ("
|
|
56
|
+
"including whitelisting safe versions of packages and docker images)."
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
return ret_code
|