diff --git a/bindata.go b/bindata.go index 935ca53..54649c9 100644 --- a/bindata.go +++ b/bindata.go @@ -1,5 +1,7 @@ // Code generated by go-bindata. DO NOT EDIT. // sources: +// templates/aws-roles-tf/deploy.sh +// templates/aws-roles-tf/main.tf // templates/rds-tf/deploy.sh // templates/rds-tf/main.tf @@ -79,6 +81,88 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } +var _bindataTemplatesAwsrolestfDeploysh = []byte( + "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8d\xc1\x4a\x03\x31\x10\x86\xef\x79\x8a\x91\xf6\x9a\xed\x33\x94\xba" + + "\x37\x2d\xd2\x55\x3c\x4f\xe3\xc4\x86\x26\x93\x90\x4c\xdc\x5d\xb6\x79\x77\x51\xa4\xf4\x50\xf0\x38\xc3\xf7\xfd\xdf" + + "\xea\x61\x73\x74\xbc\x29\x27\xa5\x56\x40\x93\x13\x18\x4f\xc4\x80\x3c\x83\x89\x21\x20\x7f\x80\x45\xe7\x8b\x2a\x24" + + "\xa0\x49\x29\xa1\x9c\xd1\xc6\x1c\xc0\xb1\x93\x9b\x73\x8c\xf9\x5c\x12\x1a\x82\x42\x9e\x8c\xc0\xb2\x40\xd7\x4f\x92" + + "\xf1\x40\x25\xd6\x6c\xa8\x74\xef\x57\xa6\x35\xb8\x5c\xe0\x9e\xcd\x34\xfe\xa7\xde\x54\x31\x25\x3f\x83\xc6\x2a\x51" + + "\x63\x4a\x39\x7e\x91\x52\xe7\x7a\x24\x23\x1e\x4c\x64\xeb\x3e\xa1\x16\xd2\x26\xb2\xd0\x24\xb0\x5e\x76\x4f\x6f\xc3" + + "\x6b\x7f\x68\x57\xea\x6f\xc2\xfe\x56\x1f\x29\xf9\x38\x07\x62\xe9\xf6\x18\x7e\x62\xfa\xce\x7b\xa8\xd6\xba\x09\x5a" + + "\xeb\x66\x0c\x1e\x34\xc3\x7a\xd9\x6f\x9f\xfb\xe1\x65\xbb\xeb\xdb\x77\x00\x00\x00\xff\xff\x6f\x63\x76\x50\x54\x01" + + "\x00\x00") + +func bindataTemplatesAwsrolestfDeployshBytes() ([]byte, error) { + return bindataRead( + _bindataTemplatesAwsrolestfDeploysh, + "templates/aws-roles-tf/deploy.sh", + ) +} + + + +func bindataTemplatesAwsrolestfDeploysh() (*asset, error) { + bytes, err := bindataTemplatesAwsrolestfDeployshBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{ + name: "templates/aws-roles-tf/deploy.sh", + size: 340, + md5checksum: "", + mode: os.FileMode(420), + modTime: time.Unix(1582728061, 0), + } + + a := &asset{bytes: bytes, info: info} + + return a, nil +} + +var _bindataTemplatesAwsrolestfMaintf = []byte( + "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x91\x3f\x8f\xe3\x20\x10\xc5\x7b\x7f\x0a\xe4\x1e\x5b\xa7\xeb\x22\x45" + + "\xba\xe2\xd2\x5c\x71\x45\x72\xbd\x85\xf1\xd8\x46\x06\xc6\x07\x43\xfe\x28\xe1\xbb\xaf\x80\x55\x94\x55\xb2\x5a\x69" + + "\xe9\x18\xfd\xde\x83\xf7\x86\xc0\x39\x31\xa2\x33\xec\x5a\x31\xd6\x0b\xb9\x80\x1d\x58\xed\x7f\xd6\x79\xc0\x58\x1f" + + "\xe4\x02\xc4\x3e\x9e\x2d\xab\xad\x38\x2a\xde\x0b\xbb\xf0\xbb\x05\x97\x68\x8c\xb0\x03\xf7\x24\x08\xea\x2c\x77\x30" + + "\x29\xb4\xcf\x72\xb1\x72\x8f\x81\x66\xfe\xa3\x70\x0b\x5c\xd8\xd3\xd9\xb2\xda\x83\x3b\x2a\x09\x5c\x09\xc3\x1d\x6a" + + "\xf0\x05\x3f\xa1\x5b\xfc\x2a\x24\x74\x0b\x5c\xba\xd5\xc1\xa8\xce\x09\x57\xc2\x64\xaa\xbd\x5e\x59\xb3\x3b\x93\x13" + + "\x7b\xf0\x18\x9c\x04\xdf\xec\xec\x51\x39\xb4\x06\x2c\xb1\x18\x33\xf1\x1b\x56\x8d\x97\x34\x69\xfe\x0a\x03\x2c\x46" + + "\xfe\x62\x7c\x08\x63\xb2\x8f\xb1\xbc\xbd\x3a\x1c\x95\x86\xa7\xaf\x4a\x33\x14\x40\x48\xfd\x32\x4b\xa9\x92\xe3\xc9" + + "\x82\xe3\x63\xd0\x9a\x4b\xb4\xe4\x50\x27\x59\xac\x62\x55\x19\x1c\x82\x86\x1c\x23\xa7\x2d\x4b\x28\x01\x1e\x8c\x26" + + "\x45\x9b\x8d\xf7\xf3\xa6\x6d\x27\x45\xbf\x26\x45\x73\xe8\x1b\x69\x86\x26\x6f\x85\x40\xce\x8d\xb2\x6d\xbe\x28\x3b" + + "\x3a\xd1\xde\xeb\x6b\x26\x45\xe9\x39\x78\x28\x23\x79\x7e\xd1\xd7\x8d\xfd\x0f\x48\xa9\xa0\xf4\x9f\xb2\x93\x2e\x19" + + "\x7e\xa2\x3d\x14\x64\x9f\x88\x1b\x33\xc1\xd3\x3f\xfc\xe3\xd1\x16\x83\x24\xec\x6c\x2a\xfc\x3d\xd0\xb7\x76\x11\xab" + + "\xb7\x00\x00\x00\xff\xff\x9e\x05\xfd\x70\xbd\x02\x00\x00") + +func bindataTemplatesAwsrolestfMaintfBytes() ([]byte, error) { + return bindataRead( + _bindataTemplatesAwsrolestfMaintf, + "templates/aws-roles-tf/main.tf", + ) +} + + + +func bindataTemplatesAwsrolestfMaintf() (*asset, error) { + bytes, err := bindataTemplatesAwsrolestfMaintfBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{ + name: "templates/aws-roles-tf/main.tf", + size: 701, + md5checksum: "", + mode: os.FileMode(420), + modTime: time.Unix(1582727097, 0), + } + + a := &asset{bytes: bytes, info: info} + + return a, nil +} + var _bindataTemplatesRdstfDeploysh = []byte( "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x8d\x41\x4e\xc4\x30\x0c\x45\xf7\x9c\xc2\x88\x75\xd3\x13\xb0\xe4\x02" + "\x6c\x58\x46\x6e\x62\x4a\x44\x13\x47\xb6\xd3\x82\xda\xde\x9d\x0d\x9a\xa9\x46\x23\xcd\x68\x76\xb6\xfe\x7f\xef\xbf" + @@ -108,7 +192,7 @@ func bindataTemplatesRdstfDeploysh() (*asset, error) { size: 373, md5checksum: "", mode: os.FileMode(420), - modTime: time.Unix(1582701520, 0), + modTime: time.Unix(1582718244, 0), } a := &asset{bytes: bytes, info: info} @@ -156,7 +240,7 @@ func bindataTemplatesRdstfMaintf() (*asset, error) { size: 1316, md5checksum: "", mode: os.FileMode(420), - modTime: time.Unix(1582701559, 0), + modTime: time.Unix(1582718244, 0), } a := &asset{bytes: bytes, info: info} @@ -228,8 +312,10 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. // var _bindata = map[string]func() (*asset, error){ - "templates/rds-tf/deploy.sh": bindataTemplatesRdstfDeploysh, - "templates/rds-tf/main.tf": bindataTemplatesRdstfMaintf, + "templates/aws-roles-tf/deploy.sh": bindataTemplatesAwsrolestfDeploysh, + "templates/aws-roles-tf/main.tf": bindataTemplatesAwsrolestfMaintf, + "templates/rds-tf/deploy.sh": bindataTemplatesRdstfDeploysh, + "templates/rds-tf/main.tf": bindataTemplatesRdstfMaintf, } // @@ -285,6 +371,10 @@ type bintree struct { var _bintree = &bintree{Func: nil, Children: map[string]*bintree{ "templates": {Func: nil, Children: map[string]*bintree{ + "aws-roles-tf": {Func: nil, Children: map[string]*bintree{ + "deploy.sh": {Func: bindataTemplatesAwsrolestfDeploysh, Children: map[string]*bintree{}}, + "main.tf": {Func: bindataTemplatesAwsrolestfMaintf, Children: map[string]*bintree{}}, + }}, "rds-tf": {Func: nil, Children: map[string]*bintree{ "deploy.sh": {Func: bindataTemplatesRdstfDeploysh, Children: map[string]*bintree{}}, "main.tf": {Func: bindataTemplatesRdstfMaintf, Children: map[string]*bintree{}}, diff --git a/main.go b/main.go index 8940c14..613a2d4 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,12 @@ package main import ( - "os" - "github.com/urfave/cli/v2" - "log" - "io/ioutil" "encoding/json" "github.com/a8m/envsubst" + "github.com/urfave/cli/v2" + "io/ioutil" + "log" + "os" ) func init() { @@ -34,32 +34,33 @@ func parseManifest(manifestPath string) (*Manifest, error) { return nil, err } manifest.ExtraResources.Workspace = workspaceMap[manifest.ExtraResources.Environment] + manifest.Deployment.NameSuffix = DEPLOYMENT_NAME_SUFFIX return &manifest, nil } func main() { app := &cli.App{ - Name: "infra-provisioner", + Name: "infra-provisioner", Version: "0.0.1", //Common flags for all subcommands - Flags: []cli.Flag { + Flags: []cli.Flag{ &cli.StringFlag{ - Name: "manifest", - Usage: "Path of the manifest file", - Aliases: []string{"m"}, + Name: "manifest", + Usage: "Path of the manifest file", + Aliases: []string{"m"}, Required: true, }, &cli.BoolFlag{ - Name: "template-only", - Usage: "Provisions just the template for given resource", + Name: "template-only", + Usage: "Provisions just the template for given resource", Aliases: []string{"t"}, }, }, Commands: []*cli.Command{ { - Name: "database", + Name: "database", Usage: "Provision database instance", Action: func(c *cli.Context) error { manifest, err := parseManifest(c.String("manifest")) @@ -75,6 +76,23 @@ func main() { return nil }, }, + { + Name: "iam-roles", + Usage: "Provision iam service roles", + Action: func(c *cli.Context) error { + manifest, err := parseManifest(c.String("manifest")) + if err != nil { + log.Fatalf("\nErr: %v", err) + return err + } + err = provisionResource("roles", "aws-roles-tf", manifest, c.Bool("template-only")) + if err != nil { + log.Fatalf("\nErr: %v", err) + return err + } + return nil + }, + }, }, } diff --git a/sample_infra_manifest.json b/sample_infra_manifest.json index a71be54..12efedf 100644 --- a/sample_infra_manifest.json +++ b/sample_infra_manifest.json @@ -1,15 +1,35 @@ { "extraResources": { - "environment": "prod", + "environment": "nonprod", "database": { "instanceName": "auth-service", "user": "auth_service_user", "password": "auth_service_password", "sizeInGb": 7, "dbNames": ["auth_service"] + }, + "service_role": { + "name": "auth-navi-service-role", + "policies": [ + { + "actions": ["s3:GetObject","s3:PutObject"], + "resource": "arn:aws:s3:::navi-e3e2a9bfd88566b05001b02a3f51d286/*" + }, + { + "actions": ["s3:GetObject","s3:PutObject"], + "resource": "arn:aws:s3:::arn:aws:s3:::test-bucket-to-be-deleted/*" + }, + { + "resource": "*", + "actions":["sns:Publish", "sns:SetSMSAttributes"] + } + ] } }, "team": { "name": "LoanOrigination" + }, + "deployment": { + "name": "auth" } } diff --git a/templates/aws-roles-tf/deploy.sh b/templates/aws-roles-tf/deploy.sh new file mode 100644 index 0000000..b036436 --- /dev/null +++ b/templates/aws-roles-tf/deploy.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# exit when any command fails +set -e + +terraform init +terraform workspace select {{ .ExtraResources.Workspace }} || terraform workspace new {{ .ExtraResources.Workspace }} +terraform apply -auto-approve + +kubectl config use-context ${CLUSTER} +kubectl apply -f {{ .Deployment.Name }}-{{ .Deployment.NameSuffix }}.yaml -n ${NAMESPACE} \ No newline at end of file diff --git a/templates/aws-roles-tf/main.tf b/templates/aws-roles-tf/main.tf new file mode 100644 index 0000000..c08c62b --- /dev/null +++ b/templates/aws-roles-tf/main.tf @@ -0,0 +1,17 @@ +terraform { + backend "s3" { + bucket = "navi-bank-terraform-command-state" + region = "ap-south-1" + key = "service-iam-roles" + workspace_key_prefix = "iamroles/{{ .ExtraResources.Environment }}/{{ .Deployment.Name }}-{{ .Deployment.NameSuffix }}" + profile = "cmd" + acl = "bucket-owner-full-control" + } +} + +module "iam-role" { + source = "git::ssh://git@github.cmd.navi-tech.in/navi-infra/iam-roles.git" + environment = {{ .ExtraResources.Environment | quote }} + service_role = {{ .ExtraResources.ServiceRole | mustToJson }} + role_name = "{{ .Deployment.Name }}-{{ .Deployment.NameSuffix }}" +} diff --git a/types.go b/types.go index 349833f..b666437 100644 --- a/types.go +++ b/types.go @@ -1,35 +1,53 @@ package main -var workspaceMap = map[string]string { - "prod": "aps1.prod.navi-tech.in", - "cmd": "prod.cmd.navi-tech.in", +var workspaceMap = map[string]string{ + "prod": "aps1.prod.navi-tech.in", + "cmd": "prod.cmd.navi-tech.in", "nonprod": "nonprod.np.navi-tech.in", - "spike": "spike.np.navi-tech.in", + "spike": "spike.np.navi-tech.in", +} + +const DEPLOYMENT_NAME_SUFFIX = "navi-service" + +type Deployment struct { + Name string `json:"name"` + NameSuffix string } type Manifest struct { ExtraResources ExtraResources `json:"extraResources"` - Team Team `json:"team"` + Team Team `json:"team"` + Deployment Deployment `json:"deployment"` } type ExtraResources struct { Environment string `json:"environment"` - Workspace string - Database Database `json:"database"` + Workspace string + Database Database `json:"database"` + ServiceRole ServiceRole `json:"service_role"` } //We provide defaults in respective terraforms instead of here to keep all values at one place type Database struct { - AwsInstanceClass string `json:"awsInstanceClass"` - PsqlFamily string `json:"psqlFamily"` - PsqlEngineVersion string `json:"psqlEngineVersion"` - User string `json:"user"` - Password string `json:"password"` - SizeInGb int `json:"sizeInGb"` - DbNames []string `json:"dbNames"` - InstanceName string `json:"instanceName"` + AwsInstanceClass string `json:"awsInstanceClass"` + PsqlFamily string `json:"psqlFamily"` + PsqlEngineVersion string `json:"psqlEngineVersion"` + User string `json:"user"` + Password string `json:"password"` + SizeInGb int `json:"sizeInGb"` + DbNames []string `json:"dbNames"` + InstanceName string `json:"instanceName"` } type Team struct { Name string `json:"name"` } + +type Policies struct { + Actions []string `json:"actions"` + Resource string `json:"resource"` +} + +type ServiceRole struct { + Policies []Policies `json:"policies"` +} diff --git a/util.go b/util.go index 88cfe1e..82115e9 100644 --- a/util.go +++ b/util.go @@ -21,4 +21,4 @@ func createFile(dir, fileName string) (*os.File, error) { os.Chmod(filePath, os.ModePerm) return file, err -} +} \ No newline at end of file