Exemple #1
0
    def test_source_valid(self):

        # write the vault password to the .pwd file
        pwd_path = "/tmp/.pwd"

        # make sure file is not present
        if os.path.exists(pwd_path):
            os.remove(pwd_path)

        # write the pwd to the file
        with open(pwd_path, "w") as text_file:
            text_file.write("open_sesame")

        secrets_vaults = [{
            "type": "keepass",
            "name": "keepass-1",
            "configs": {
                "vault-path": "yac/tests/vaults/vectors/test_vault.kdbx",
                "vault-pwd-path": pwd_path
            }
        }]

        vaults = SecretVaults(secrets_vaults)

        # get the results keepass vault and assert that it is available
        vault = vaults.get_vault('keepass-1')

        self.assertTrue(vault)
Exemple #2
0
    def test_json_file_source(self):

        secrets_vaults = [
          {
              "type": "file",
              "name": "file-1",
              "configs": {
                "vault-path": "yac/tests/vault/vectors/file_vault.json"
              }

          }
        ]

        vaults = SecretVaults(secrets_vaults)
        vaults.initialize({})
        # get the results keepass vault and assert that it is available
        vault = vaults.get_vault('file-1')

        self.assertTrue(vault)
Exemple #3
0
    def test_source_valid(self):

        secrets_vaults = [
          {
              "type": "s3",
              "name": "s3",
              "configs": {
                "bucket": "gitlab-secure",
                "vault-path": "secrets/s3_vault.json"
              }
             
          }
        ]

        vaults = SecretVaults(secrets_vaults)
        
        # get the resulting s3 vault and assert that it is ready
        vault = vaults.get_vault('s3')

        self.assertTrue(vault.is_ready())  
Exemple #4
0
    def test_source_invalid(self):

        # vault-pwd is an invalid config setting for keepass
        secrets_vaults = [{
            "type": "keepass",
            "name": "keepass-1",
            "configs": {
                "vault-path": "yac/tests/vaults/vectors/test_vault.kdbx",
                "vault-pwd": "/path/does/not/matter/for/this/test"
            }
        }]

        # test that these invalid vault configs don't throw a validation error
        vaults = SecretVaults(secrets_vaults)

        self.assertTrue(vaults)
Exemple #5
0
    def test_secrets(self):

        my_secrets = {
            "param-key-1": {
                "comment": "branch 1, child 1, entry 1",
                "source": "keepass",
                "lookup": {
                    "path": "Branch 1/B1-C1/B1-C1-E1",
                    "field": "password"
                }
            },
            "param-key-2": {
                "comment": "branch 2, child 2, entry 1",
                "source": "keepass",
                "lookup": {
                    "path": "Branch 2/B2-C2/B2-C2-E1",
                    "field": "password"
                }
            }
        }

        secrets_vaults = [{
            "type": "keepass",
            "name": "keepass",
            "configs": {
                "vault-path": "yac/tests/vault/vectors/test_vault.kdbx",
                "vault-pwd-path": TestCase.pwd_path
            }
        }]

        params = Params({})

        vaults = SecretVaults(secrets_vaults)

        secrets = Secrets(my_secrets)

        secrets.load(params, vaults)

        print(secrets.get_errors())

        both_loaded = (params.get("param-key-1") == 'b1-c1-e1-secret'
                       and params.get("param-key-2") == 'b2-c2-e1-secret')

        self.assertTrue(both_loaded)
Exemple #6
0
    def test_file_contents(self):

        secrets_vaults = [{
            "type": "b64",
            "name": "my-file",
            "configs": {
                "vault-path": "yac/tests/vault/vectors/b64_vault.yaml"
            }
        }]

        vaults = SecretVaults(secrets_vaults)
        vaults.initialize({})

        self.assertTrue(vaults.get("my-file", "secret1") == "secret1 value")

        self.assertTrue(vaults.get("my-file", "secret2.prod") == "prod value")

        self.assertTrue(vaults.get("my-file", "secret3[1]") == "val2")
Exemple #7
0
    def test_schema_good(self):

        serialized_obj = [{
            "type": "s3",
            "name": "main",
            "configs": {
                "comment": "vault is in our nonprod v2 account",
                "bucket": "gitlab-secrets-dots",
                "vault-path": "gitlab-secrets.json",
                "format": "json"
            }
        }, {
            "type": "file",
            "name": "local",
            "configs": {
                "comment": "vault is in a local file",
                "vault-path": "/opt/gitlab/etc/secrets.yaml",
                "format": "yaml"
            }
        }, {
            "type": "keepass",
            "name": "keepass",
            "configs": {
                "comment": "vault is in a local keepass vault",
                "vault-path": "/opt/etc/vault.kdbx",
                "vault-pwd-path": "/tmp/.pwd"
            }
        }]

        # test that no schema validation errors are raised
        validation_success = True
        try:
            secrets = SecretVaults(serialized_obj)
        except ValidationError as e:
            validation_success = False
            print("validation failed")

        self.assertTrue(validation_success == True)
Exemple #8
0
    def __init__(self,
                 serialized_service,
                 service_path,
                 alias="",
                 params_path="",
                 kvps=""):

        # first validate. this should throw an exception if
        # required fields aren't present
        validate(serialized_service, "yac/schema/service.json")

        self.path = service_path
        self.kvps_str = kvps
        self.params_file_path = params_path

        self.description = Description(search('Description',
                                       serialized_service,{}),
                                       alias)

        self.vaults = SecretVaults(search('"Vaults"',
                                      serialized_service,[]))

        # a service can references other services that it includes
        self.includes = search("includes",
                             serialized_service,{})

        # initialize stack params (key/value pairs and maps), including static params specified
        # in the serialized service, params from an external file,
        # params specified in a key-value pair string (kvps),
        self.params = Params(search('"Params"',
                                    serialized_service, {}))

        # initialize the dictionary that will hold all params (statics+secrets+inputs)
        self.all_params = {}

        inputs_cacher = InputsCacher(search('InputsCache',
                                    serialized_service,{}))

        self.inputs = Inputs(search('Inputs',
                                    serialized_service,{}),
                             inputs_cacher)

        self.secrets = Secrets(search('"Secrets"',
                                      serialized_service,{}))

        # inialize the stack associated with this service
        self.stack = Stack(search('Stack',
                                  serialized_service, {}))

        self.tasks = Tasks(search('Tasks',
                                    serialized_service,{}))

        # initialize the tests associated with this service
        self.tests = IntegrationTests(search('"IntegrationTests"',
                                      serialized_service,{}))

        # initialize the artifacts associate with this service
        self.artifacts = Artifacts(search('Artifacts',
                                           serialized_service,[]))

        # initialize the credentialer associated with this service
        self.credentialers = Credentialers(search("Credentialers",serialized_service,[]))

        # initialize the pipeline associated with this service
        self.pipeline = Pipeline(search('Pipeline',
                                     serialized_service,{}))

        # load the objects from each included service
        self.load_includes()

        # save a copy of the full serialized version of the
        # service to support the serialize() method
        self.serialized_service = serialized_service
Exemple #9
0
class Service():

    def __init__(self,
                 serialized_service,
                 service_path,
                 alias="",
                 params_path="",
                 kvps=""):

        # first validate. this should throw an exception if
        # required fields aren't present
        validate(serialized_service, "yac/schema/service.json")

        self.path = service_path
        self.kvps_str = kvps
        self.params_file_path = params_path

        self.description = Description(search('Description',
                                       serialized_service,{}),
                                       alias)

        self.vaults = SecretVaults(search('"Vaults"',
                                      serialized_service,[]))

        # a service can references other services that it includes
        self.includes = search("includes",
                             serialized_service,{})

        # initialize stack params (key/value pairs and maps), including static params specified
        # in the serialized service, params from an external file,
        # params specified in a key-value pair string (kvps),
        self.params = Params(search('"Params"',
                                    serialized_service, {}))

        # initialize the dictionary that will hold all params (statics+secrets+inputs)
        self.all_params = {}

        inputs_cacher = InputsCacher(search('InputsCache',
                                    serialized_service,{}))

        self.inputs = Inputs(search('Inputs',
                                    serialized_service,{}),
                             inputs_cacher)

        self.secrets = Secrets(search('"Secrets"',
                                      serialized_service,{}))

        # inialize the stack associated with this service
        self.stack = Stack(search('Stack',
                                  serialized_service, {}))

        self.tasks = Tasks(search('Tasks',
                                    serialized_service,{}))

        # initialize the tests associated with this service
        self.tests = IntegrationTests(search('"IntegrationTests"',
                                      serialized_service,{}))

        # initialize the artifacts associate with this service
        self.artifacts = Artifacts(search('Artifacts',
                                           serialized_service,[]))

        # initialize the credentialer associated with this service
        self.credentialers = Credentialers(search("Credentialers",serialized_service,[]))

        # initialize the pipeline associated with this service
        self.pipeline = Pipeline(search('Pipeline',
                                     serialized_service,{}))

        # load the objects from each included service
        self.load_includes()

        # save a copy of the full serialized version of the
        # service to support the serialize() method
        self.serialized_service = serialized_service

    # add mergeable fields from another service into this service
    def add(self,
            service):

        if service.params:

            self.params.add(service.params)

        if service.secrets:

            self.secrets.add(service.secrets)

        if service.vaults:

            self.vaults.add(service.vaults)

        if service.stack.impl:

            # there can be only one stack
            if self.stack.impl:
                self.stack.add(service.stack)
            else:
                self.stack = service.stack

        if service.tasks:

            self.tasks.add(service.tasks)

        if service.inputs:

            self.inputs.add(service.inputs)

        if service.tests:

            self.tests.add(service.tests)

        if service.artifacts:

            self.artifacts.add(service.artifacts)

        if service.credentialers:

            self.credentialers.add(service.credentialers)

        if service.pipeline and service.pipeline.get_stages():

            # there can be only one pipeline per service
            self.pipeline = service.pipeline

    def add_params_via_kvps(self,kvp_str):
        # load key-value pairs via a kvp string formatted as:
        # <key1>:<value1>,<key2>:<val2>,etc
        self.params.load_kvps(kvp_str)

    def load_includes(self):
        # load objects from each included service

        # for each included service specified
        for service_key in self.includes:

            sub_service_path = self.includes[service_key]["value"]

            # load the included service ...
            this_sub, err = get_service(sub_service_path,
                                   servicefile_path=self.path)

            # add to this service
            if not err:
                print("including '%s' service ..."%(service_key))
                self.add(this_sub)
            else:
                print("included service '%s' could not be loaded from %s"%(service_key,
                                                                           sub_service_path))
                print("error: %s"%err)
                print("exiting ...")
                exit(0)

                exit(0)

    def get_meta_params(self):
        # get meta data about this service

        service_metadata = Params({})
        service_metadata.set("service-default-alias",self.description.default_alias, "service default alias")
        service_metadata.set("service-alias",self.description.alias, "service alias")
        service_metadata.set("service-name",self.description.name, "service name")

        service_metadata.set("servicefile-path",self.path, "path to the servicefile")

        # add service summary and repo
        service_metadata.set('service-summary',self.description.summary, "service summary")
        service_metadata.set('service-repo',self.description.repo, "repo containing this service")

        # add the command that was run against this service
        service_metadata.set("yac-command",sys.argv[0], 'the yac command being run')

        return service_metadata

    def get_params(self):

        # add params describing the service itself
        self.params.add(self.get_meta_params())

        # load any params from yac-supported env variables
        self.params.load_from_env_variables()

        # load kvps (typically used for injecting inputs in pipelines or overriding
        #   an invidual param setpoint)
        self.params.load_kvps(self.kvps_str)

        # load params from file
        self.params.load_from_file(self.params_file_path)

        return self.params

    def get_all_params(self,
                       context="",
                       dry_run_bool=False,
                       credentialer_names=[]):

        # Take a copy of params
        self.all_params = self.get_params()

        # process inputs and load results into params
        self.inputs.load(self.all_params)

        # load secrets into params
        self.secrets.load(self.all_params,
                          self.vaults)

        return self.all_params

    def get_description(self):

        return self.description

    def get_artifacts(self):

        return self.artifacts

    def get_stack(self):

        return self.stack

    def get_tests(self):

        return self.tests

    def get_tasks(self):

        return self.tasks

    def get_vaults(self):

        return self.vaults

    def get_deployer(self):

        return self.deployer()

    def get_inputs(self):

        return self.inputs

    def get_secrets(self):

        return self.secrets

    def get_pipeline(self):

        return self.pipeline

    def get_credentialers(self):

        return self.credentialers

    def get_serialized_pipeline(self):

        return self.serialized_pipeline

    def deploy_boot_files(self, dry_run_bool=False):

        self.boot_files.deploy(self.params, dry_run_bool)

    def serialize(self):
        return self.serialized_service

    def __str__(self):
        ret = ("description:\n %s\n"%self.description +
               "params:\n %s\n"%self.params +
               "secrets:\n %s\n"%self.secrets +
               "stack:\n %s\n"%self.stack +
               "vaults: \n %s\n")%self.vaults
        return ret