diff --git a/awx/main/models/credential/__init__.py b/awx/main/models/credential/__init__.py index c731001f42..5bfbba0184 100644 --- a/awx/main/models/credential/__init__.py +++ b/awx/main/models/credential/__init__.py @@ -1216,6 +1216,26 @@ ManagedCredentialType( }, ) +ManagedCredentialType( + namespace='terraform', + kind='cloud', + name=gettext_noop('Terraform backend configuration'), + managed=True, + inputs={ + 'fields': [ + { + 'id': 'configuration', + 'label': gettext_noop('Backend configuration'), + 'type': 'string', + 'secret': True, + 'multiline': True, + 'help_text': gettext_noop('Terraform backend config as Hashicorp configuration language.'), + }, + ], + 'required': ['configuration'], + }, +) + class CredentialInputSource(PrimordialModel): class Meta: diff --git a/awx/main/models/credential/injectors.py b/awx/main/models/credential/injectors.py index 93c1a37d8b..585bd9597d 100644 --- a/awx/main/models/credential/injectors.py +++ b/awx/main/models/credential/injectors.py @@ -122,3 +122,11 @@ def kubernetes_bearer_token(cred, env, private_data_dir): env['K8S_AUTH_SSL_CA_CERT'] = to_container_path(path, private_data_dir) else: env['K8S_AUTH_VERIFY_SSL'] = 'False' + + +def terraform(cred, env, private_data_dir): + handle, path = tempfile.mkstemp(dir=os.path.join(private_data_dir, 'env')) + with os.fdopen(handle, 'w') as f: + os.chmod(path, stat.S_IRUSR | stat.S_IWUSR) + f.write(cred.get_input('configuration')) + env['TF_BACKEND_CONFIG_FILE'] = to_container_path(path, private_data_dir) diff --git a/awx/main/tests/functional/test_credential.py b/awx/main/tests/functional/test_credential.py index c018e735bf..97cf2beb2d 100644 --- a/awx/main/tests/functional/test_credential.py +++ b/awx/main/tests/functional/test_credential.py @@ -101,6 +101,7 @@ def test_default_cred_types(): 'satellite6', 'scm', 'ssh', + 'terraform', 'thycotic_dsv', 'thycotic_tss', 'vault', diff --git a/awx/main/tests/unit/test_tasks.py b/awx/main/tests/unit/test_tasks.py index aa1e63c906..703dc72f77 100644 --- a/awx/main/tests/unit/test_tasks.py +++ b/awx/main/tests/unit/test_tasks.py @@ -1085,6 +1085,27 @@ class TestJobCredentials(TestJobExecution): assert open(env['ANSIBLE_NET_SSH_KEYFILE'], 'r').read() == self.EXAMPLE_PRIVATE_KEY assert safe_env['ANSIBLE_NET_PASSWORD'] == HIDDEN_PASSWORD + def test_terraform_cloud_credentials(self, job, private_data_dir, mock_me): + terraform = CredentialType.defaults['terraform']() + hcl_config = ''' + backend "s3" { + bucket = "s3_sample_bucket" + key = "/tf_state/" + region = "us-east-1" + } + ''' + credential = Credential(pk=1, credential_type=terraform, inputs={'configuration': hcl_config}) + credential.inputs['configuration'] = encrypt_field(credential, 'configuration') + job.credentials.add(credential) + + env = {} + safe_env = {} + credential.credential_type.inject_credential(credential, env, safe_env, [], private_data_dir) + + local_path = to_host_path(env['TF_BACKEND_CONFIG_FILE'], private_data_dir) + config = open(local_path, 'r').read() + assert config == hcl_config + def test_custom_environment_injectors_with_jinja_syntax_error(self, private_data_dir, mock_me): some_cloud = CredentialType( kind='cloud',