dflook / cloudformation-dns-certificate

Cloudformation DNS Validated Certificate Resource
MIT License
48 stars 13 forks source link

Cross-Account Usage Failing #5

Closed snowake4me closed 5 years ago

snowake4me commented 5 years ago

Hi Daniel-

First and foremost - thanks for this excellent repo, which I've used with great success to automate the creation and provisioning of ACM certificates with Route53 HostedZone DNS verification. Super-slick with the inline Lambda to create the required validation records!

I'm not trying to leverage in a more complex environment, where the Route53 HostedZone is in another account than where I'm trying to generate / issue the certs. I've created the role in the account with the Route53 Hosted Zone:

arn:aws:iam::############:role/RoleAllowedToEditHostedZone

which has the appropriate permissions to manage the hosted zone.

However, when the template runs (from the 'target' account, where I'm creating the certificate) - it fails, every time, when it gets to the certificate resource. It throws the error:

Failed to create resource. Parameter validation failed: Unknown parameter in input: "Route53RoleArn", must be one of: DomainName, ValidationMethod, SubjectAlternativeNames, IdempotencyToken, DomainValidationOptions, Options, CertificateAuthorityArn

This makes sense to me, since the Route53RoleArn doesn't appear in the CloudFormation docs for that resource type:

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-certificatemanager-certificate.html

Am I reading your docs wrong? Ahh - I see that it's not actually a resource of Type: AWS::CertificateManager::Certificate - but rather, Custom::DNSCertificate - so perhaps this IS a valid attribute / parameter for this object type?

Any guidance / assistance is much appreciated: Thank You!

dflook commented 5 years ago

Hi, thanks for creating an issue.

It looks like your using the standard AWS::CertificateManager::Certificate resource; You're correct the certificate resource type should be Custom::DNSCertificate (or AWS::CloudFormation::CustomResource, either will work), with a ServiceToken: !GetAtt 'CustomAcmCertificateLambda.Arn' property.

It should then accept the Route53RoleArn property.

Let me know of this works, and I'll try and improve the documentation.

snowake4me commented 5 years ago

Thanks for the quick response - and, sorry for the confusion: I'm not actually using the AWS::CertificateManager::Certificate resource type: Here's the excerpt that is that resource definition:

myCertificate: Properties: Route53RoleArn: !Ref pRoute53AssumedRoleArn DomainName: !Ref pCertificateSubject DomainValidationOptions:

  • DomainName: !Ref pCertificateSubject HostedZoneId: !Ref pHostedZoneId ServiceToken: !GetAtt 'CustomAcmCertificateLambda.Arn' Tags:
  • Key: Name Value: !Ref pCertificateSubject
  • Key: Owner Value: !Ref pCFNOwnerTag
  • Key: App Value: !Ref pAppName
  • Key: Env Value: !Ref pEnv ValidationMethod: DNS Type: Custom::DNSCertificate

Apologies: Seems no matter how I copy/paste, my indentation of the above YAML isn't being preserved. I don't think that's the problem...

I'm happy to post my full template: I added a user-friendly Interface in the Metadata section, and added some additional tags used by my org, so it will look a bit different - but all the core functionality is yours. THANK YOU again!!

Let me know if I can provide any additional insight or details - again, still fully acknowledging that I'm just 'failing to follow instructions'. :)

Cheers!

snowake4me commented 5 years ago

Hmm - it just occurred to me:

I had 'forked' this code, and have been working on a feature branch within my own copy of the code - and made a lot of other edits, as noted above. What JUST struck me was:

I forked the code before the recent PR which introduced this new feature - so -- I'll bet, aside from the other changes (noted in the README.md) - there are also changes to the inline Lambda.

Time to re-clone, make it work as is - and then, I can retrofit my edits - and even offer it back as a potential PR if there's any interest.

Sorry for the distraction - and I'll report back here with my findings.

snowake4me commented 5 years ago

Eureka! I got the cross-account provisioning working - though not without some tweaks. In my environment, the local Lambda functions were a bit under-permissioned (I get getting an error and rollback when it attempted to apply the Tag to the Certificate Request - weird, huh?). I had also slightly under-scoped my 'assumed role' in the account containing the Route53 HostedZone - so I over-permissioned both, and got it working (WooT!!) - now to go back and 'least-privilege' both sides. Once I get it dialed in, I'll report back - as well as re-apply my parameterization and Interface changes.

Thanks again for this great resource!

pitkley commented 5 years ago

@snowake4me it is great to see that somebody else has a use for the role-assumption feature, and I'm glad to hear that you got it working!

In case it is of use, following is the role I am currently assuming and using with success:

ACMRecordCreationRole:
  Type: AWS::IAM::Role
  Properties:
    AssumeRolePolicyDocument:
      Statement:
      - Action:
        - sts:AssumeRole
        Principal:
          AWS:
          - arn:aws:iam::TRUSTED-ACCOUNT-ID:root
        Effect: Allow
      Version: '2012-10-17'
    Policies:
    - PolicyName: 'ACMRecordCreation'
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Action:
          - route53:ChangeResourceRecordSets
          Resource:
          - arn:aws:route53:::hostedzone/YOURHOSTEDZONEID
          Effect: Allow
    RoleName: ACMRecordCreationRole

(You'd obviously need to replace TRUSTED-ACCOUNT-ID and YOURHOSTEDZONEID.)

In the lambda execution role I only added the following statement, the rest I have kept identical to what the example provides.

- Action:
  - sts:AssumeRole
  Resource:
  - arn:aws:iam::TRUSTING-ACCOUNT-ID:role/ACMRecordCreationRole
  Effect: Allow