From a6b28269b6df71a5bab3651f408cb19c178b9153 Mon Sep 17 00:00:00 2001 From: "T.J. Corrigan" Date: Thu, 25 Aug 2016 11:19:42 -0500 Subject: [PATCH] adding support for built-in AWS policies --- .../cloudformation/model/resource/IAM.scala | 22 +++++++++- .../model/resource/IAMRole_UT.scala | 41 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/test/scala/com/monsanto/arch/cloudformation/model/resource/IAMRole_UT.scala diff --git a/src/main/scala/com/monsanto/arch/cloudformation/model/resource/IAM.scala b/src/main/scala/com/monsanto/arch/cloudformation/model/resource/IAM.scala index ed0796cb..af91f98d 100644 --- a/src/main/scala/com/monsanto/arch/cloudformation/model/resource/IAM.scala +++ b/src/main/scala/com/monsanto/arch/cloudformation/model/resource/IAM.scala @@ -81,10 +81,30 @@ object `AWS::IAM::ManagedPolicy` extends DefaultJsonProtocol { implicit val format: JsonFormat[`AWS::IAM::ManagedPolicy`] = jsonFormat8(`AWS::IAM::ManagedPolicy`.apply) } + +case class AWSManagedPolicy(name: String) { + def buildARN = s"arn:aws:iam::aws:policy/$name" +} + +case class ManagedPolicyARN private(resource: Either[ResourceRef[`AWS::IAM::ManagedPolicy`], AWSManagedPolicy]) +object ManagedPolicyARN extends DefaultJsonProtocol { + implicit val format: JsonFormat[ManagedPolicyARN] = new JsonFormat[ManagedPolicyARN]{ + def write(obj: ManagedPolicyARN) = + obj.resource match { + case Left(ref) => ref.toJson + case Right(arn) => JsString(arn.buildARN) + } + def read(json: JsValue) = ??? + } + + implicit def fromAWSManagedPolicy(p: AWSManagedPolicy): ManagedPolicyARN = ManagedPolicyARN(Right(p)) + implicit def fromManagedPolicy(p: ResourceRef[`AWS::IAM::ManagedPolicy`]): ManagedPolicyARN = ManagedPolicyARN(Left(p)) +} + case class `AWS::IAM::Role`( name: String, AssumeRolePolicyDocument: PolicyDocument, - ManagedPolicyArns: Option[Seq[ResourceRef[`AWS::IAM::ManagedPolicy`]]] = None, + ManagedPolicyArns: Option[Seq[ManagedPolicyARN]] = None, Path: Option[Token[String]] = None, Policies: Option[Seq[Policy]] = None, override val Condition: Option[ConditionRef] = None diff --git a/src/test/scala/com/monsanto/arch/cloudformation/model/resource/IAMRole_UT.scala b/src/test/scala/com/monsanto/arch/cloudformation/model/resource/IAMRole_UT.scala new file mode 100644 index 00000000..0f533134 --- /dev/null +++ b/src/test/scala/com/monsanto/arch/cloudformation/model/resource/IAMRole_UT.scala @@ -0,0 +1,41 @@ +package com.monsanto.arch.cloudformation.model.resource + +import com.monsanto.arch.cloudformation.model.ResourceRef +import org.scalatest.{FunSpec, Matchers} +import spray.json.{JsObject, JsString, _} + + +class IAMRole_UT extends FunSpec with Matchers { + describe("AWS::IAM::Role") { + + it("should handle both AWS Managed and Customer policies into valid json") { + val customerPolicy = `AWS::IAM::ManagedPolicy`("customer-policy", PolicyDocument(Seq())) + val awsPolicy = AWSManagedPolicy("AdministratorAccess") + + val fakePolicyDoc = PolicyDocument(Seq( + PolicyStatement( + "Allow", + Some(DefinedPrincipal(Map("Service" -> Seq("config.amazonaws.com")))), + Seq("sts:AssumeRole") + ) + )) + + val expectedJson = JsObject( + "name" -> JsString("role"), + "AssumeRolePolicyDocument" -> fakePolicyDoc.toJson, + "ManagedPolicyArns" -> JsArray( + JsObject("Ref" -> JsString("customer-policy")), + JsString("arn:aws:iam::aws:policy/AdministratorAccess") + ) + ) + + val role = `AWS::IAM::Role`( + "role", + fakePolicyDoc, + ManagedPolicyArns = Some(Seq(ResourceRef(customerPolicy), awsPolicy)) + ) + + role.toJson should be(expectedJson) + } + } +}