Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New AWS SSM parameter module #50215

Merged
merged 2 commits into from
Oct 25, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/topics/releases/neon.rst
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ Module Changes
``dns`` can be overriden by ``ipv4dns`` or ``ipv6dns``). The ``proto`` option
is now required.

- Added new :py:func:`boto_ssm <salt.modules.boto_ssm>` module to set and query
secrets in AWS SSM parameters.

Salt Cloud Features
===================

Expand Down
147 changes: 147 additions & 0 deletions salt/modules/boto_ssm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# -*- coding: utf-8 -*-
'''
Connection module for Amazon SSM

:configuration: This module accepts explicit ssm credentials but can also
utilize IAM roles assigned to the instance through Instance Profiles. Dynamic
credentials are then automatically obtained from AWS API and no further
configuration is necessary. More Information available at:

.. code-block:: text

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html

If IAM roles are not used you need to specify them either in a pillar or
in the minion's config file:

.. code-block:: yaml

ssm.keyid: GKTADJGHEIQSXMKKRBJ08H
ssm.key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs

A region may also be specified in the configuration:

.. code-block:: yaml

ssm.region: us-east-1

If a region is not specified, the default is us-east-1.

It's also possible to specify key, keyid and region via a profile, either
as a passed in dict, or as a string to pull from pillars or minion config:

.. code-block:: yaml

myprofile:
keyid: GKTADJGHEIQSXMKKRBJ08H
key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
region: us-east-1

:depends: boto3
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import logging

# Import Salt libs
import salt.utils.versions
import salt.utils.json as json

log = logging.getLogger(__name__)


def __virtual__():
'''
Only load if boto libraries exist.
'''
has_boto_reqs = salt.utils.versions.check_boto_reqs()
if has_boto_reqs is True:
__utils__['boto3.assign_funcs'](__name__, 'ssm')
return has_boto_reqs


def get_parameter(name, withdecryption=False, resp_json=False, region=None, key=None, keyid=None, profile=None):
'''
Retrives a parameter from SSM Parameter Store

.. versionadded:: Neon

.. code-block:: text

salt-call boto_ssm.get_parameter test-param withdescription=True
'''
conn = __utils__['boto3.get_connection']('ssm', region=region, key=key, keyid=keyid, profile=profile)
try:
resp = conn.get_parameter(Name=name, WithDecryption=withdecryption)
except conn.exceptions.ParameterNotFound:
log.warning("get_parameter: Unable to locate name: %s", name)
return False

if resp_json:
return json.loads(resp['Parameter']['Value'])
else:
return resp['Parameter']['Value']


def put_parameter(Name,
Value,
Description=None,
Type='String',
KeyId=None,
Overwrite=False,
AllowedPattern=None,
region=None,
key=None,
keyid=None,
profile=None):
'''
Sets a parameter in the SSM parameter store

.. versionadded:: Neon

.. code-block:: text

salt-call boto_ssm.put_parameter test-param test_value Type=SecureString KeyId=alias/aws/ssm Description='test encrypted key'
'''
conn = __utils__['boto3.get_connection']('ssm', region=region, key=key, keyid=keyid, profile=profile)
if Type not in ('String', 'StringList', 'SecureString'):
raise AssertionError('Type needs to be String|StringList|SecureString')
if Type == 'SecureString' and not KeyId:
raise AssertionError('Require KeyId with SecureString')

boto_args = {}
if Description:
boto_args['Description'] = Description
if KeyId:
boto_args['KeyId'] = KeyId
if AllowedPattern:
boto_args['AllowedPattern'] = AllowedPattern

try:
resp = conn.put_parameter(Name=Name, Value=Value, Type=Type, Overwrite=Overwrite, **boto_args)
except conn.exceptions.ParameterAlreadyExists:
log.warning("The parameter already exists."
" To overwrite this value, set the Overwrite option in the request to True")
return False
return resp['Version']


def delete_parameter(Name, region=None, key=None, keyid=None, profile=None):
'''
Removes a parameter from the SSM parameter store

.. versionadded:: Neon

.. code-block:: text
salt-call boto_ssm.delete_parameter test-param
'''
conn = __utils__['boto3.get_connection']('ssm', region=region, key=key, keyid=keyid, profile=profile)
try:
resp = conn.delete_parameter(Name=Name)
except conn.exceptions.ParameterNotFound:
log.warning("delete_parameter: Unable to locate name: %s", Name)
return False
if resp['ResponseMetadata']['HTTPStatusCode'] == 200:
return True
else:
return False