From 5811750616d6531e0f44e75ca92a1c6bcf70366c Mon Sep 17 00:00:00 2001 From: Jim Minter Date: Wed, 25 Mar 2020 16:48:52 -0600 Subject: [PATCH] grant acrPull to RP SP --- deploy/rp-global.json | 24 ++++++++++++++++++++ pkg/deploy/bindata.go | 23 ++++++++++++++++++++ pkg/deploy/generator/const.go | 1 + pkg/deploy/generator/generators.go | 4 ++++ pkg/deploy/generator/resources.go | 15 +++++++++++++ pkg/deploy/generator/templates.go | 19 ++++++++++++++++ pkg/deploy/predeploy.go | 35 ++++++++++++++++++++++++++++++ 7 files changed, 121 insertions(+) create mode 100644 deploy/rp-global.json diff --git a/deploy/rp-global.json b/deploy/rp-global.json new file mode 100644 index 000000000..9ac714131 --- /dev/null +++ b/deploy/rp-global.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "acrResourceId": { + "type": "string" + }, + "rpServicePrincipalId": { + "type": "string" + } + }, + "resources": [ + { + "name": "[concat(substring(parameters('acrResourceId'), add(lastIndexOf(parameters('acrResourceId')), 1)), '/'), '/Microsoft.Authorization/', guid(parameters('acrResourceId'), parameters('rpServicePrincipalId'), 'RP / AcrPull'))]", + "type": "Microsoft.ContainerRegistry/registries/providers/roleAssignments", + "properties": { + "scope": "[parameters('acrResourceId')]", + "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "principalId": "[parameters('rpServicePrincipalId')]" + }, + "apiVersion": "2015-07-01" + } + ] +} diff --git a/pkg/deploy/bindata.go b/pkg/deploy/bindata.go index 342e9bcd4..79e7bb6ab 100644 --- a/pkg/deploy/bindata.go +++ b/pkg/deploy/bindata.go @@ -6,6 +6,7 @@ // rp-development-predeploy.json // rp-development.json // rp-global-subscription-production.json +// rp-global.json // rp-production-managed-identity.json // rp-production-parameters.json // rp-production-predeploy-parameters.json @@ -207,6 +208,26 @@ func rpGlobalSubscriptionProductionJson() (*asset, error) { return a, nil } +var _rpGlobalJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x93\xcf\x8e\xda\x30\x10\xc6\xef\x3c\x85\xe5\x56\x0a\x48\x49\x9c\x2c\x50\xb6\xdc\x50\x7b\xd9\x43\x55\x44\xab\x5e\x10\x07\xd7\x1e\xc0\x55\x62\x5b\x33\xce\xaa\x6c\xc5\xbb\x57\x4e\xb6\x0b\xa1\x2c\xd2\x2a\x92\x15\xf9\x1b\xfd\xe6\x9b\x3f\xfe\x33\x60\x8c\x31\xfe\x9e\xd4\x1e\x6a\xc9\xe7\x8c\xef\x43\xf0\x34\x17\xa2\xbb\xc9\x6b\x69\xe5\x0e\x6a\xb0\x21\x97\x4f\x0d\x42\xae\x5c\xfd\xac\x91\xb8\x2b\xca\x69\x56\x94\x59\x51\x0a\x0d\xbe\x72\x87\x18\xf7\x1d\x6a\x5f\xc9\x00\xf9\x2f\x72\xf6\x1d\x4f\xbb\x0c\xca\xd9\x00\x36\xfc\x00\x24\xe3\x6c\x4c\x54\xe6\x45\xfc\xfe\x05\x78\x89\xb2\x86\x00\x48\x7c\xce\x3a\x5b\xed\xbd\x54\xb8\x02\x72\x0d\x2a\x78\xd0\x3d\xa9\x95\xc3\xc1\x43\xa4\x51\x40\x63\x77\xfc\x45\x3c\xa6\x27\x04\xfa\x6f\x80\x8f\x46\xc1\x12\x8d\x55\xc6\xcb\xea\x4d\xa4\xc1\x19\x8f\xe3\xb3\x97\xe8\x72\xfd\x12\x73\x81\xb2\xb2\x6e\x51\x6b\xe5\xac\x92\x61\x48\xcd\xcf\x8e\x3a\x3c\x55\x39\x4c\x7a\x95\x25\xa3\x94\x49\xad\x87\x95\xa4\xf0\x60\x35\xfc\xfe\xba\xbd\x15\x3c\x4a\x59\x19\x8f\x44\x24\xed\xf9\xc5\x28\x74\xe4\xb6\x21\x5f\x34\x61\xef\xd0\x3c\xc9\x60\x9c\x15\x49\xca\x76\x8d\xd1\xb7\xf3\x9e\x8b\xd7\x7a\xd5\xa6\x58\x2d\x99\x60\x0b\x85\xcb\xa6\xaa\x92\xd1\x68\xc3\xd3\xeb\xed\x3b\x39\xf9\xe4\x6c\x90\xc6\x02\xae\x60\x67\x28\xe0\x41\x60\xf7\x63\x80\x84\x47\xf7\x68\x34\x20\x09\x74\x15\x2c\x88\xcc\xce\xc6\xed\xa1\x4b\xae\x47\xe7\x01\x83\x01\xfa\x6f\x64\xad\x4e\xca\x75\x89\xd7\x37\x6a\xbc\x74\xdb\x8d\xd2\x55\xf0\x19\xb6\xc6\x9a\xd8\xaa\x76\x25\xf8\x3a\x8e\x4a\xa1\xf1\xf1\xea\x44\x18\x26\xaf\x35\xb8\x0f\xa1\x24\x65\xc9\x6c\xfb\x71\x5a\x6a\x2d\xb3\x09\xe8\x71\x36\xf9\x70\x5f\x64\x72\xa6\x64\x36\x19\x6f\xa1\x9c\xdd\xe9\xe9\xf8\xfe\x35\x4b\xbe\xb7\xa0\xfd\x92\xae\x4f\x66\xc3\x7b\x94\xe3\x45\xf7\xa4\x37\x67\x4f\xae\x7b\xaf\xb3\xac\x28\x2f\xd7\x7b\x33\x38\x0e\xfe\x06\x00\x00\xff\xff\x3b\xdd\x27\x3a\x0c\x04\x00\x00") + +func rpGlobalJsonBytes() ([]byte, error) { + return bindataRead( + _rpGlobalJson, + "rp-global.json", + ) +} + +func rpGlobalJson() (*asset, error) { + bytes, err := rpGlobalJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "rp-global.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + var _rpProductionManagedIdentityJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x90\x41\x6b\xf3\x30\x0c\x86\xef\xfd\x15\x26\xdf\x07\x69\xa1\x71\xe2\x8e\xc1\xe8\x6d\xa7\xd1\x43\x61\xb0\xb1\x4b\xe9\xc1\x38\x6a\xeb\x91\xd8\x46\x92\x0b\x5d\xe9\x7f\x1f\x49\x93\xb4\xcd\x6d\xf6\x45\x48\xaf\xa4\xf7\xd1\x79\x22\x84\x10\xc9\x7f\x32\x07\xa8\x75\xb2\x14\xc9\x81\x39\xd0\x32\xcf\xaf\x19\x59\x6b\xa7\xf7\x50\x83\x63\xa9\x7f\x22\x82\x34\xbe\xee\x6a\x94\x2f\x0a\xf5\x9c\x15\x2a\x2b\x54\x5e\x42\xa8\xfc\xa9\xd1\x7d\x42\x1d\x2a\xcd\x20\xbf\xc9\xbb\x7f\xc9\xfc\xba\xc1\x78\xc7\xe0\xf8\x0b\x90\xac\x77\xcd\x22\x25\x8b\xe6\xf7\x02\x04\xf2\x11\x0d\x50\xb2\x14\x9b\x36\xd5\xbc\xf3\x10\xb5\x22\x3e\x05\x68\x7a\xd7\xd6\xa0\x27\xbf\x63\xb9\x6e\xfd\x95\xab\x12\x1c\x5b\x3e\xe5\x91\x00\x5f\x89\xec\xde\x0d\x49\x0b\xd4\x2d\x19\xe6\x38\x5d\xb7\x73\x30\x64\xb6\xeb\x1c\x4b\x2a\x6f\x34\x77\x56\x37\xbd\xb9\x37\xf4\x31\x4c\x67\xb2\x2f\x6e\xc7\x5d\x3a\xd8\x3b\xc4\x45\xa1\x5e\x32\xa5\xb2\xa7\x22\x19\x64\x97\x36\xda\x76\xd4\x3e\x72\x88\xdc\x30\xdf\x48\x13\x0c\x1f\x80\x47\x6b\xe0\x1d\xad\x33\x36\xe8\x6a\x55\x3e\x28\x1e\x6e\x41\x8c\xd6\xed\xc7\x46\x8e\xba\x8a\xd0\x79\xdf\x01\x82\x33\x30\xed\x29\x56\xe5\x34\xfd\xeb\x05\xd3\xb9\x48\xef\xae\x95\xce\xe6\x22\xbd\xe1\xa5\x33\x19\x6e\x5e\xb7\x63\xda\xcb\xe4\x32\xf9\x0d\x00\x00\xff\xff\x34\xd4\x95\xa9\x6a\x02\x00\x00") func rpProductionManagedIdentityJsonBytes() ([]byte, error) { @@ -365,6 +386,7 @@ var _bindata = map[string]func() (*asset, error){ "rp-development-predeploy.json": rpDevelopmentPredeployJson, "rp-development.json": rpDevelopmentJson, "rp-global-subscription-production.json": rpGlobalSubscriptionProductionJson, + "rp-global.json": rpGlobalJson, "rp-production-managed-identity.json": rpProductionManagedIdentityJson, "rp-production-parameters.json": rpProductionParametersJson, "rp-production-predeploy-parameters.json": rpProductionPredeployParametersJson, @@ -419,6 +441,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "rp-development-predeploy.json": {rpDevelopmentPredeployJson, map[string]*bintree{}}, "rp-development.json": {rpDevelopmentJson, map[string]*bintree{}}, "rp-global-subscription-production.json": {rpGlobalSubscriptionProductionJson, map[string]*bintree{}}, + "rp-global.json": {rpGlobalJson, map[string]*bintree{}}, "rp-production-managed-identity.json": {rpProductionManagedIdentityJson, map[string]*bintree{}}, "rp-production-parameters.json": {rpProductionParametersJson, map[string]*bintree{}}, "rp-production-predeploy-parameters.json": {rpProductionPredeployParametersJson, map[string]*bintree{}}, diff --git a/pkg/deploy/generator/const.go b/pkg/deploy/generator/const.go index 21ab26ce2..f39d5ad67 100644 --- a/pkg/deploy/generator/const.go +++ b/pkg/deploy/generator/const.go @@ -19,6 +19,7 @@ const ( FileRPProductionPredeployParameters = "rp-production-predeploy-parameters.json" FileRPProduction = "rp-production.json" FileRPProductionParameters = "rp-production-parameters.json" + FileRPProductionGlobal = "rp-global.json" FileRPProductionGlobalSubscription = "rp-global-subscription-production.json" fileEnvDevelopment = "env-development.json" diff --git a/pkg/deploy/generator/generators.go b/pkg/deploy/generator/generators.go index 1c1e31f5e..036efb177 100644 --- a/pkg/deploy/generator/generators.go +++ b/pkg/deploy/generator/generators.go @@ -39,6 +39,10 @@ func (g *generator) Artifacts() error { if err != nil { return err } + err = g.writeTemplate(g.rpGlobalTemplate(), FileRPProductionGlobal) + if err != nil { + return err + } err = g.writeTemplate(g.rpGlobalSubscriptionTemplate(), FileRPProductionGlobalSubscription) if err != nil { return err diff --git a/pkg/deploy/generator/resources.go b/pkg/deploy/generator/resources.go index 13a93a4d5..122f94947 100644 --- a/pkg/deploy/generator/resources.go +++ b/pkg/deploy/generator/resources.go @@ -1392,3 +1392,18 @@ func (g *generator) rbac() []*arm.Resource { }, } } + +func (g *generator) rpAcrRbac() *arm.Resource { + return &arm.Resource{ + Resource: &mgmtauthorization.RoleAssignment{ + Name: to.StringPtr("[concat(substring(parameters('acrResourceId'), add(lastIndexOf(parameters('acrResourceId')), 1)), '/'), '/Microsoft.Authorization/', guid(parameters('acrResourceId'), parameters('rpServicePrincipalId'), 'RP / AcrPull'))]"), + Type: to.StringPtr("Microsoft.ContainerRegistry/registries/providers/roleAssignments"), + Properties: &mgmtauthorization.RoleAssignmentPropertiesWithScope{ + Scope: to.StringPtr("[parameters('acrResourceId')]"), + RoleDefinitionID: to.StringPtr("[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]"), + PrincipalID: to.StringPtr("[parameters('rpServicePrincipalId')]"), + }, + }, + APIVersion: apiVersions["authorization"], + } +} diff --git a/pkg/deploy/generator/templates.go b/pkg/deploy/generator/templates.go index c89f24b74..4e0841242 100644 --- a/pkg/deploy/generator/templates.go +++ b/pkg/deploy/generator/templates.go @@ -89,6 +89,25 @@ func (g *generator) rpTemplate() *arm.Template { return t } +func (g *generator) rpGlobalTemplate() *arm.Template { + t := templateStanza() + + params := []string{ + "rpServicePrincipalId", + "acrResourceId", + } + + for _, param := range params { + t.Parameters[param] = &arm.TemplateParameter{Type: "string"} + } + + t.Resources = append(t.Resources, + g.rpAcrRbac(), + ) + + return t +} + func (g *generator) rpGlobalSubscriptionTemplate() *arm.Template { t := templateStanza() diff --git a/pkg/deploy/predeploy.go b/pkg/deploy/predeploy.go index a8f34f6e1..a209f551a 100644 --- a/pkg/deploy/predeploy.go +++ b/pkg/deploy/predeploy.go @@ -44,6 +44,11 @@ func (d *deployer) PreDeploy(ctx context.Context) (string, error) { return "", err } + err = d.deployGlobal(ctx, rpServicePrincipalID) + if err != nil { + return "", err + } + // deploy NSGs, keyvaults err = d.deployPreDeploy(ctx, rpServicePrincipalID) if err != nil { @@ -63,6 +68,36 @@ func (d *deployer) PreDeploy(ctx context.Context) (string, error) { return rpServicePrincipalID, nil } +func (d *deployer) deployGlobal(ctx context.Context, rpServicePrincipalID string) error { + deploymentName := "rp-global" + + b, err := Asset(generator.FileRPProductionGlobal) + if err != nil { + return err + } + + var template map[string]interface{} + err = json.Unmarshal(b, &template) + if err != nil { + return err + } + + parameters := d.getParameters(template["parameters"].(map[string]interface{})) + parameters.Parameters["rpServicePrincipalId"] = &arm.ParametersParameter{ + Value: rpServicePrincipalID, + } + + d.log.Infof("deploying global") + return d.globaldeployments.CreateOrUpdateAndWait(ctx, d.config.Configuration.GlobalResourceGroupName, deploymentName, mgmtresources.Deployment{ + Properties: &mgmtresources.DeploymentProperties{ + Template: template, + Mode: mgmtresources.Incremental, + Parameters: parameters.Parameters, + }, + Location: to.StringPtr("centralus"), + }) +} + func (d *deployer) deployGlobalSubscription(ctx context.Context) error { deploymentName := "rp-global-subscription"