Skip to content

Commit

Permalink
GCP support
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesWoolfenden committed Sep 1, 2022
1 parent 24a2e38 commit d2bd2a6
Show file tree
Hide file tree
Showing 19 changed files with 273 additions and 75 deletions.
3 changes: 0 additions & 3 deletions src/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,3 @@ var awsAcmCertificate []byte

//go:embed mapping/aws/resource/acm-pa/aws_acmpca_certificate_authority.json
var awsAcmpcaCertificateAuthority []byte

//go:embed mapping/gcp/google_compute_instance.json
var googleComputeInstance []byte
8 changes: 8 additions & 0 deletions src/files_gcp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package pike

import (
_ "embed" // required for embed
)

//go:embed mapping/gcp/resource/google_compute_instance.json
var googleComputeInstance []byte
26 changes: 21 additions & 5 deletions src/gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,28 @@ import (
// GetGCPPermissions for GCP resources
func GetGCPPermissions(result ResourceV2) []string {
var Permissions []string
switch result.Name {
case "googleComputeInstance":
Permissions = GetPermissionMap(googleComputeInstance, result.Attributes)
if result.TypeName == "resource" {
Permissions = GetGCPResourcePermissions(result)
} else {
Permissions = GetGCPDataPermissions(result)
}

return Permissions
}

// GetGCPResourcePermissions looks up permissions required for resources
func GetGCPResourcePermissions(result ResourceV2) []string {
TFLookup := map[string]interface{}{
"google_compute_instance": googleComputeInstance,
}

var Permissions []string

default:
log.Printf("%s not yet implemented", result.Name)
temp := TFLookup[result.Name]
if temp != nil {
Permissions = GetPermissionMap(TFLookup[result.Name].([]byte), result.Attributes)
} else {
log.Printf("%s not implemented", result.Name)
}

return Permissions
Expand Down
20 changes: 20 additions & 0 deletions src/gcp_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package pike

import "log"

// GetGCPDataPermissions gets permissions required for datasources
func GetGCPDataPermissions(result ResourceV2) []string {

TFLookup := map[string]interface{}{}

var Permissions []string

temp := TFLookup[result.Name]
if temp != nil {
Permissions = GetPermissionMap(TFLookup[result.Name].([]byte), result.Attributes)
} else {
log.Printf("data.%s not implemented", result.Name)
}

return Permissions
}
39 changes: 39 additions & 0 deletions src/gcp_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package pike

import (
"bytes"
_ "embed" //required for embed
"strings"
"text/template"
)

//go:embed terraform.gcppolicy.template
var policyGCPTemplate []byte

// GCPPolicy create an IAM policy
func GCPPolicy(permissions []string) (string, error) {
test := strings.Join(permissions, "\", \n\t \"")

type GCPPolicyDetails struct {
Name string
Project string
RoleID string
Permissions string
}

PolicyName := "terraform" + randSeq(8)
theDetails := GCPPolicyDetails{PolicyName, "examplea", "terraform_pike", test}

var output bytes.Buffer
tmpl, err := template.New("test").Parse(string(policyGCPTemplate))
if err != nil {
panic(err)
}

err = tmpl.Execute(&output, theDetails)

if err != nil {
panic(err)
}
return output.String(), nil
}
13 changes: 0 additions & 13 deletions src/mapping/gcp/google_compute_instance.json

This file was deleted.

25 changes: 25 additions & 0 deletions src/mapping/gcp/resource/google_compute_instance.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[
{
"apply": [
"compute.zones.get",
"compute.instances.create",
"compute.instances.get",
"compute.disks.create",
"compute.disks.create",
"compute.subnetworks.use",
"compute.subnetworks.useExternalIp",
"compute.instances.setMetadata",
"compute.instances.delete"
],
"attributes": {
"tags": [
"compute.instances.setTags"
]
},
"destroy": [
"compute.instances.delete"
],
"modify": [],
"plan": []
}
]
54 changes: 40 additions & 14 deletions src/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"encoding/json"
"errors"
"fmt"
"log"
"reflect"
"sort"
"strconv"
"strings"
Expand All @@ -15,8 +17,8 @@ import (
//go:embed terraform.policy.template
var policyTemplate []byte

// NewPolicy constructor
func NewPolicy(Actions []string) Policy {
// NewAWSPolicy constructor
func NewAWSPolicy(Actions []string) Policy {
something := Policy{}
something.Version = "2012-10-17"

Expand Down Expand Up @@ -54,29 +56,53 @@ func NewPolicy(Actions []string) Policy {

// GetPolicy creates new iam polices from a list of Permissions
func GetPolicy(actions Sorted, output string) (string, error) {
var Permissions []string

Permissions = append(Permissions, actions.AWS...)
v := reflect.ValueOf(actions)
typeOfV := v.Type()
values := make([]interface{}, v.NumField())

if Permissions == nil {
return "", errors.New("no permissions detected")
}
var Policy string
var err error
for i := 0; i < v.NumField(); i++ {
values[i] = v.Field(i).Interface()
switch typeOfV.Field(i).Name {
case "AWS":
//AWSPermissions = append(AWSPermissions, actions.AWS...)

//dedupe
Permissions = unique(Permissions)
if actions.AWS == nil {
continue
}
//dedupe
AWSPermissions := unique(actions.AWS)
Policy, err = AWSPolicy(AWSPermissions, output)

Policy, err2 := AWSPolicy(Permissions, output)
if err != nil {
log.Print(err)
continue
}

if err2 != nil {
return "", err2
case "GCP":
if actions.GCP == nil {
continue
}
//dedupe
GCPPermissions := unique(actions.GCP)
Policy, err = GCPPolicy(GCPPermissions)
if err != nil {
log.Print(err)
continue
}
}
}
if Policy == "" {
return Policy, errors.New("No permissions found")
}

return Policy, nil
}

// AWSPolicy create an IAM policy
func AWSPolicy(Permissions []string, output string) (string, error) {
Policy := NewPolicy(Permissions)
Policy := NewAWSPolicy(Permissions)
b, err := json.MarshalIndent(Policy, "", " ")
if err != nil {
fmt.Println(err)
Expand Down
2 changes: 1 addition & 1 deletion src/policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestNewPolicy(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NewPolicy(tt.args.Actions); !reflect.DeepEqual(got, tt.want) {
if got := NewAWSPolicy(tt.args.Actions); !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewPolicy() = %v, want %v", got, tt.want)
}
})
Expand Down
2 changes: 1 addition & 1 deletion src/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func MakePolicy(dirName string, output string, file string, init bool) (string,
}

PermissionBag.AWS = append(PermissionBag.AWS, newPerms.AWS...)
PermissionBag.GCP = append(PermissionBag.GCP, newPerms.AWS...)
PermissionBag.GCP = append(PermissionBag.GCP, newPerms.GCP...)
}

Policy, err2 := GetPolicy(PermissionBag, output)
Expand Down
9 changes: 9 additions & 0 deletions src/terraform.gcppolicy.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "google_project_iam_custom_role" "{{.Name}}" {
project = "{{.Project}}"
role_id = "{{.RoleID}}"
title = "{{.Name}}"
description = "A user with least privileges"
permissions= [
"{{ .Permissions }}"
]
}
21 changes: 21 additions & 0 deletions terraform/gcp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
clean:
-rm -fr .terraform
-rm .terraform.lock.hcl
-rm terraform.tfstate
-rm terraform.tfstate.backup
apply: init
terraform apply -auto-approve

plan: init
terraform plan

destroy: init
terraform destroy -auto-approve

init:
terraform init

role: FORCE
terraform -chdir=./role apply -auto-approve

FORCE:
40 changes: 40 additions & 0 deletions terraform/gcp/backup/google_compute_instance.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
resource "google_compute_instance" "default" {
name = "test"
machine_type = "e2-micro"
zone = "europe-west2-a"



boot_disk {
initialize_params {
image = "debian-cloud/debian-11"
}
}

// Local SSD disk
# scratch_disk {
# interface = "SCSI"
# }

network_interface {
network = "default"

access_config {
// Ephemeral public IP
}
}

metadata = {
foo = "bar"
}

metadata_startup_script = "echo hi > /test.txt"

# service_account {
# # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
# email = google_service_account.default.email
# scopes = ["cloud-platform"]
# }

tags = ["foo", "bar"]
}
38 changes: 0 additions & 38 deletions terraform/gcp/gcp_instance.tf

This file was deleted.

6 changes: 6 additions & 0 deletions terraform/gcp/provider.google.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
provider "google" {
project = "examplea"
region = "europe-west2"
zone = "europe-west2-a"
credentials = "/Users/jameswoolfenden/examplea-pike.json"
}
8 changes: 8 additions & 0 deletions terraform/gcp/role/google_project_iam_binding.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resource "google_project_iam_binding" "pike" {
project = "examplea"
role = google_project_iam_custom_role.pike.id

members = [
"serviceAccount:${google_service_account.pike.email}",
]
}
Loading

0 comments on commit d2bd2a6

Please sign in to comment.