Lambda policy arn (#38863)
* Fix the function_name handling logic for lambda_policy Switch the logic handling function_names that are ARNs so that ARNs are correctly handled and detected * Add tests for lambda_policy function_arn Ensure that function_arn works. Needs a reasonable ansible_lambda_role.
This commit is contained in:
parent
4e56dcd01a
commit
0b4f92d852
3 changed files with 81 additions and 64 deletions
|
@ -188,6 +188,13 @@ def validate_params(module):
|
||||||
|
|
||||||
# validate function name
|
# validate function name
|
||||||
if function_name.startswith('arn:'):
|
if function_name.startswith('arn:'):
|
||||||
|
if not re.search(r'^[\w\-:]+$', function_name):
|
||||||
|
module.fail_json(
|
||||||
|
msg='ARN {0} is invalid. ARNs must contain only alphanumeric characters, hyphens and colons.'.format(function_name)
|
||||||
|
)
|
||||||
|
if len(function_name) > 140:
|
||||||
|
module.fail_json(msg='ARN name "{0}" exceeds 140 character limit'.format(function_name))
|
||||||
|
else:
|
||||||
if not re.search(r'^[\w\-]+$', function_name):
|
if not re.search(r'^[\w\-]+$', function_name):
|
||||||
module.fail_json(
|
module.fail_json(
|
||||||
msg='Function name {0} is invalid. Names must contain only alphanumeric characters and hyphens.'.format(
|
msg='Function name {0} is invalid. Names must contain only alphanumeric characters and hyphens.'.format(
|
||||||
|
@ -196,13 +203,6 @@ def validate_params(module):
|
||||||
if len(function_name) > 64:
|
if len(function_name) > 64:
|
||||||
module.fail_json(
|
module.fail_json(
|
||||||
msg='Function name "{0}" exceeds 64 character limit'.format(function_name))
|
msg='Function name "{0}" exceeds 64 character limit'.format(function_name))
|
||||||
else:
|
|
||||||
if not re.search(r'^[\w\-:]+$', function_name):
|
|
||||||
module.fail_json(
|
|
||||||
msg='ARN {0} is invalid. ARNs must contain only alphanumeric characters, hyphens and colons.'.format(function_name)
|
|
||||||
)
|
|
||||||
if len(function_name) > 140:
|
|
||||||
module.fail_json(msg='ARN name "{0}" exceeds 140 character limit'.format(function_name))
|
|
||||||
|
|
||||||
|
|
||||||
def get_qualifier(module):
|
def get_qualifier(module):
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Principal": {
|
||||||
|
"Service": "lambda.amazonaws.com"
|
||||||
|
},
|
||||||
|
"Action": "sts:AssumeRole"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -5,6 +5,15 @@
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
|
|
||||||
|
- name: set up AWS credentials
|
||||||
|
set_fact:
|
||||||
|
aws_connection_info: &aws_connection_info
|
||||||
|
aws_region: '{{ aws_region }}'
|
||||||
|
aws_access_key: '{{ aws_access_key }}'
|
||||||
|
aws_secret_key: '{{ aws_secret_key }}'
|
||||||
|
security_token: '{{ security_token }}'
|
||||||
|
no_log: yes
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
- name: test with no parameters
|
- name: test with no parameters
|
||||||
lambda_policy:
|
lambda_policy:
|
||||||
|
@ -54,7 +63,6 @@
|
||||||
- name: test exceptions generated by forcing bad ec2 url
|
- name: test exceptions generated by forcing bad ec2 url
|
||||||
lambda_policy:
|
lambda_policy:
|
||||||
function_name: "{{ lambda_function_name }}"
|
function_name: "{{ lambda_function_name }}"
|
||||||
region: "{{ec2_region}}"
|
|
||||||
state: present
|
state: present
|
||||||
statement_id: api-gateway-invoke-lambdas
|
statement_id: api-gateway-invoke-lambdas
|
||||||
action: lambda:InvokeFunction
|
action: lambda:InvokeFunction
|
||||||
|
@ -89,38 +97,43 @@
|
||||||
dest: "{{output_dir}}/mini_http_lambda.zip"
|
dest: "{{output_dir}}/mini_http_lambda.zip"
|
||||||
register: zip_res
|
register: zip_res
|
||||||
|
|
||||||
|
# This should exist, but there's no expectation that the test user should be able to
|
||||||
|
# create/update this role, merely validate that it's there.
|
||||||
|
# Use ansible -m iam_role -a 'name=ansible_lambda_role
|
||||||
|
# assume_role_policy_document={{ lookup("file", "test/integration/targets/lambda_policy/files/minimal_trust_policy.json", convert_data=False) }}
|
||||||
|
# ' -vvv localhost
|
||||||
|
# to create this through more privileged credentials before running this test suite.
|
||||||
|
- name: create minimal lambda role
|
||||||
|
iam_role:
|
||||||
|
name: ansible_lambda_role
|
||||||
|
assume_role_policy_document: "{{ lookup('file', 'minimal_trust_policy.json', convert_data=False) }}"
|
||||||
|
create_instance_profile: no
|
||||||
|
<<: *aws_connection_info
|
||||||
|
register: iam_role
|
||||||
|
|
||||||
|
- name: wait 10 seconds for role to become available
|
||||||
|
pause:
|
||||||
|
seconds: 10
|
||||||
|
when: iam_role.changed
|
||||||
|
|
||||||
- name: test state=present - upload the lambda
|
- name: test state=present - upload the lambda
|
||||||
lambda:
|
lambda:
|
||||||
name="{{lambda_function_name}}"
|
name: "{{lambda_function_name}}"
|
||||||
runtime="python2.7"
|
runtime: "python2.7"
|
||||||
handler="mini_http_lambda.handler"
|
handler: "mini_http_lambda.handler"
|
||||||
role="ansible_lambda_role"
|
role: "ansible_lambda_role"
|
||||||
ec2_region='{{ec2_region}}'
|
zip_file: "{{zip_res.dest}}"
|
||||||
aws_access_key='{{aws_access_key}}'
|
<<: *aws_connection_info
|
||||||
aws_secret_key='{{aws_secret_key}}'
|
|
||||||
security_token='{{security_token}}'
|
|
||||||
zip_file="{{zip_res.dest}}"
|
|
||||||
register: lambda_result
|
register: lambda_result
|
||||||
|
|
||||||
- name: install aws cli - FIXME temporary this should go for a lighterweight solution
|
|
||||||
command: pip install awscli
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: get the aws account ID for use in future commands
|
- name: get the aws account ID for use in future commands
|
||||||
command: aws sts get-caller-identity --output text --query 'Account'
|
aws_caller_facts:
|
||||||
environment:
|
<<: *aws_connection_info
|
||||||
AWS_ACCESS_KEY_ID: '{{aws_access_key}}'
|
register: aws_caller_facts
|
||||||
AWS_SECRET_ACCESS_KEY: '{{aws_secret_key}}'
|
|
||||||
AWS_SESSION_TOKEN: '{{security_token}}'
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: register account id
|
|
||||||
set_fact:
|
|
||||||
aws_account_id: "{{ result.stdout | replace('\n', '') }}"
|
|
||||||
|
|
||||||
- name: register lambda uri for use in template
|
- name: register lambda uri for use in template
|
||||||
set_fact:
|
set_fact:
|
||||||
mini_lambda_uri: "arn:aws:apigateway:{{ec2_region}}:lambda:path/2015-03-31/functions/arn:aws:lambda:{{ec2_region}}:{{aws_account_id}}:function:{{ lambda_result.configuration.function_name }}/invocations"
|
mini_lambda_uri: "arn:aws:apigateway:{{ aws_region }}:lambda:path/2015-03-31/functions/arn:aws:lambda:{{ aws_region }}:{{ aws_caller_facts.account }}:function:{{ lambda_result.configuration.function_name }}/invocations"
|
||||||
|
|
||||||
- name: build API file
|
- name: build API file
|
||||||
template:
|
template:
|
||||||
|
@ -131,19 +144,16 @@
|
||||||
aws_api_gateway:
|
aws_api_gateway:
|
||||||
api_file: "{{output_dir}}/endpoint-test-swagger-api.yml.j2"
|
api_file: "{{output_dir}}/endpoint-test-swagger-api.yml.j2"
|
||||||
stage: "lambdabased"
|
stage: "lambdabased"
|
||||||
region: '{{ec2_region}}'
|
<<: *aws_connection_info
|
||||||
aws_access_key: '{{aws_access_key}}'
|
|
||||||
aws_secret_key: '{{aws_secret_key}}'
|
|
||||||
security_token: '{{security_token}}'
|
|
||||||
register: create_result
|
register: create_result
|
||||||
|
|
||||||
|
|
||||||
- name: register api id for later
|
- name: register api id for later
|
||||||
set_fact:
|
set_fact:
|
||||||
api_id: "{{ create_result.api_id }}"
|
api_id: "{{ create_result.api_id }}"
|
||||||
|
|
||||||
- name: check API fails with permissions failure
|
- name: check API fails with permissions failure
|
||||||
uri: url="https://{{create_result.api_id}}.execute-api.{{ec2_region}}.amazonaws.com/lambdabased/mini/Mr_Ansible_Tester"
|
uri:
|
||||||
|
url: "https://{{create_result.api_id}}.execute-api.{{aws_region}}.amazonaws.com/lambdabased/mini/Mr_Ansible_Tester"
|
||||||
register: unauth_uri_result
|
register: unauth_uri_result
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
|
||||||
|
@ -156,18 +166,26 @@
|
||||||
- name: give api gateway execute permissions on lambda
|
- name: give api gateway execute permissions on lambda
|
||||||
lambda_policy:
|
lambda_policy:
|
||||||
function_name: "{{ lambda_function_name }}"
|
function_name: "{{ lambda_function_name }}"
|
||||||
region: "{{ec2_region}}"
|
|
||||||
state: present
|
state: present
|
||||||
statement_id: api-gateway-invoke-lambdas
|
statement_id: api-gateway-invoke-lambdas
|
||||||
action: lambda:InvokeFunction
|
action: lambda:InvokeFunction
|
||||||
principal: apigateway.amazonaws.com
|
principal: apigateway.amazonaws.com
|
||||||
source_arn: "arn:aws:execute-api:{{ ec2_region }}:{{ aws_account_id }}:*/*"
|
source_arn: "arn:aws:execute-api:{{ aws_region }}:{{ aws_caller_facts.account }}:*/*"
|
||||||
aws_access_key: '{{aws_access_key}}'
|
<<: *aws_connection_info
|
||||||
aws_secret_key: '{{aws_secret_key}}'
|
|
||||||
security_token: '{{security_token}}'
|
- name: try again but with ARN
|
||||||
|
lambda_policy:
|
||||||
|
function_name: "{{ lambda_result.configuration.function_arn }}"
|
||||||
|
state: present
|
||||||
|
statement_id: api-gateway-invoke-lambdas
|
||||||
|
action: lambda:InvokeFunction
|
||||||
|
principal: apigateway.amazonaws.com
|
||||||
|
source_arn: "arn:aws:execute-api:{{ aws_region }}:{{ aws_caller_facts.account }}:*/*"
|
||||||
|
<<: *aws_connection_info
|
||||||
|
|
||||||
- name: check API works with execute permissions
|
- name: check API works with execute permissions
|
||||||
uri: url="https://{{create_result.api_id}}.execute-api.{{ec2_region}}.amazonaws.com/lambdabased/mini/Mr_Ansible_Tester"
|
uri:
|
||||||
|
url: "https://{{create_result.api_id}}.execute-api.{{aws_region}}.amazonaws.com/lambdabased/mini/Mr_Ansible_Tester"
|
||||||
register: uri_result
|
register: uri_result
|
||||||
|
|
||||||
- name: assert API works success
|
- name: assert API works success
|
||||||
|
@ -180,10 +198,7 @@
|
||||||
aws_api_gateway:
|
aws_api_gateway:
|
||||||
api_file: "{{output_dir}}/endpoint-test-swagger-api.yml.j2"
|
api_file: "{{output_dir}}/endpoint-test-swagger-api.yml.j2"
|
||||||
stage: "lambdabased"
|
stage: "lambdabased"
|
||||||
region: '{{ec2_region}}'
|
<<: *aws_connection_info
|
||||||
aws_access_key: '{{aws_access_key}}'
|
|
||||||
aws_secret_key: '{{aws_secret_key}}'
|
|
||||||
security_token: '{{security_token}}'
|
|
||||||
register: create_result
|
register: create_result
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
|
||||||
|
@ -193,26 +208,16 @@
|
||||||
# ============================================================
|
# ============================================================
|
||||||
- name: destroy lambda for test cleanup if created
|
- name: destroy lambda for test cleanup if created
|
||||||
lambda:
|
lambda:
|
||||||
name="{{lambda_function_name}}"
|
name: "{{lambda_function_name}}"
|
||||||
ec2_region='{{ec2_region}}'
|
<<: *aws_connection_info
|
||||||
ec2_access_key='{{ec2_access_key}}'
|
state: absent
|
||||||
ec2_secret_key='{{ec2_secret_key}}'
|
|
||||||
security_token='{{security_token}}'
|
|
||||||
state=absent
|
|
||||||
register: result
|
register: result
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: destroy API for test cleanup if created
|
- name: destroy API for test cleanup if created
|
||||||
aws_api_gateway:
|
aws_api_gateway:
|
||||||
state: absent
|
state: absent
|
||||||
api_id: '{{api_id}}'
|
api_id: '{{api_id}}'
|
||||||
region: '{{ec2_region}}'
|
<<: *aws_connection_info
|
||||||
aws_access_key: '{{ec2_access_key}}'
|
|
||||||
aws_secret_key: '{{ec2_secret_key}}'
|
|
||||||
security_token: '{{security_token}}'
|
|
||||||
register: destroy_result
|
register: destroy_result
|
||||||
|
ignore_errors: yes
|
||||||
- name: assert destroy statements succeeded
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'destroy_result.changed == True'
|
|
||||||
- 'result is not failed'
|
|
||||||
|
|
Loading…
Reference in a new issue