Skip to content

Commit

Permalink
This change adds a bare-bones azure module.
Browse files Browse the repository at this point in the history
For a project I'm working on I have been writing Terratest style code to
help make assertions about infrastructure in Azure. I want to contribute
these back to Terratest to give back to the awesome open source
community you have going here.

I am initially submitting a subset of the work I have done in order to
get initial feedback. Once this PR is merged I'll go ahead and update
the remaining modules that I have to be consistent with the PR comments
provided here.

Modules in this commit:
* Azure Container Registry - Webhook + Network ACL queries
* Azure Networking - VNET/Subnet queries

Modules that I will contribute in follow on PRs:
* Azure CLI - Log into local azure CLI
* WebApp - Query for WebApp config and CD Webhook metadata
* KeyVault - Inspect network ACLs for KeyVault
  • Loading branch information
Nick Iodice committed Jul 15, 2019
1 parent 71a1fe9 commit 1395c9d
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ required = [
name = "github.com/aws/aws-sdk-go"
version = "1.14.26"

[[constraint]]
name = "github.com/Azure/azure-sdk-for-go"
version = "31.1.0"

[[constraint]]
name = "github.com/Azure/go-autorest"
version = "12.3.0"

[[constraint]]
name = "github.com/google/uuid"
version = "0.2.0"
Expand Down
101 changes: 101 additions & 0 deletions modules/azure/acr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package azure

import (
"context"
"testing"

"github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2017-10-01/containerregistry"
)

func registriesClientE(subscriptionID string) (*containerregistry.RegistriesClient, error) {
authorizer, err := DeploymentServicePrincipalAuthorizer()
if err != nil {
return nil, err
}
client := containerregistry.NewRegistriesClient(subscriptionID)
client.Authorizer = authorizer
return &client, nil
}

func webhookClientE(subscriptionID string) (*containerregistry.WebhooksClient, error) {
authorizer, err := DeploymentServicePrincipalAuthorizer()
if err != nil {
return nil, err
}
client := containerregistry.NewWebhooksClient(subscriptionID)
client.Authorizer = authorizer
return &client, nil
}

// ACRNetworkAclsE - Return the newtwork ACLs for an ACR instance
func ACRNetworkAclsE(subscriptionID string, resourceGroupName string, acrName string) (*containerregistry.NetworkRuleSet, error) {

client, err := registriesClientE(subscriptionID)
if err != nil {
return nil, err
}

acr, err := client.Get(context.Background(), resourceGroupName, acrName)
if err != nil {
return nil, err
}

return acr.NetworkRuleSet, nil
}

// ACRNetworkAcls - Like ACRNetworkAclsE but fails in the case an error is returned
func ACRNetworkAcls(t *testing.T, subscriptionID string, resourceGroupName string, acrName string) *containerregistry.NetworkRuleSet {
acls, err := ACRNetworkAclsE(subscriptionID, resourceGroupName, acrName)
if err != nil {
t.Fatal(err)
}
return acls
}

// ACRWebHookE - Return ACR Webhook definition
func ACRWebHookE(subscriptionID string, resourceGroupName string, acrName string, webhookName string) (*containerregistry.Webhook, error) {
client, err := webhookClientE(subscriptionID)
if err != nil {
return nil, err
}

webhook, err := client.Get(context.Background(), resourceGroupName, acrName, webhookName)
if err != nil {
return nil, err
}

return &webhook, nil
}

// ACRWebHook - Like ACRWebHookE but fails in the case an error is returned
func ACRWebHook(t *testing.T, subscriptionID string, resourceGroupName string, acrName string, webhookName string) *containerregistry.Webhook {
webhooks, err := ACRWebHookE(subscriptionID, resourceGroupName, acrName, webhookName)
if err != nil {
t.Fatal(err)
}
return webhooks
}

// ACRWebHookCallbackE - Get callback config for a webhook
func ACRWebHookCallbackE(subscriptionID string, resourceGroupName string, acrName string, webhookName string) (*containerregistry.CallbackConfig, error) {
client, err := webhookClientE(subscriptionID)
if err != nil {
return nil, err
}

webhookCallback, err := client.GetCallbackConfig(context.Background(), resourceGroupName, acrName, webhookName)
if err != nil {
return nil, err
}

return &webhookCallback, nil
}

// ACRWebHookCallback - Like ACRWebHookCallbackE but fails in the case an error is returned
func ACRWebHookCallback(t *testing.T, subscriptionID string, resourceGroupName string, acrName string, webhookName string) *containerregistry.CallbackConfig {
webhookCallback, err := ACRWebHookCallbackE(subscriptionID, resourceGroupName, acrName, webhookName)
if err != nil {
t.Fatal(err)
}
return webhookCallback
}
33 changes: 33 additions & 0 deletions modules/azure/authorizer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package azure

import (
"os"

"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/adal"
az "github.com/Azure/go-autorest/autorest/azure"
)

// DeploymentServicePrincipalAuthorizer - Returns an authorizer configured with the service principal
// used to execute the terraform commands
func DeploymentServicePrincipalAuthorizer() (autorest.Authorizer, error) {
return ServicePrincipalAuthorizer(
os.Getenv("ARM_CLIENT_ID"),
os.Getenv("ARM_CLIENT_SECRET"),
az.PublicCloud.ResourceManagerEndpoint)
}

// ServicePrincipalAuthorizer - Configures a service principal authorizer that can be used to create bearer tokens
func ServicePrincipalAuthorizer(clientID string, clientSecret string, resource string) (autorest.Authorizer, error) {
oauthConfig, err := adal.NewOAuthConfig(az.PublicCloud.ActiveDirectoryEndpoint, os.Getenv("ARM_TENANT_ID"))
if err != nil {
return nil, err
}

token, err := adal.NewServicePrincipalToken(*oauthConfig, clientID, clientSecret, resource)
if err != nil {
return nil, err
}

return autorest.NewBearerAuthorizer(token), nil
}
4 changes: 4 additions & 0 deletions modules/azure/azure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package azure

// azure - This package contains terratest functions that make interacting with Microsoft's Azure
// platform simpler
49 changes: 49 additions & 0 deletions modules/azure/network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package azure

import (
"context"
"testing"

"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-12-01/network"
)

func vnetClient(subscriptionID string) (*network.VirtualNetworksClient, error) {
authorizer, err := DeploymentServicePrincipalAuthorizer()
if err != nil {
return nil, err
}

client := network.NewVirtualNetworksClient(subscriptionID)
client.Authorizer = authorizer
return &client, err
}

// VnetSubnetsListE - Return the subnets that exist wihin a given VNET
func VnetSubnetsListE(subscriptionID string, resourceGroupName string, vnetName string) ([]string, error) {

client, err := vnetClient(subscriptionID)
if err != nil {
return nil, err
}

vnet, err := client.Get(context.Background(), resourceGroupName, vnetName, "")
if err != nil {
return nil, err
}

subnets := make([]string, len(*vnet.VirtualNetworkPropertiesFormat.Subnets))
for index, subnet := range *vnet.VirtualNetworkPropertiesFormat.Subnets {
subnets[index] = *subnet.ID
}

return subnets, nil
}

// VnetSubnetsList - Like VnetSubnetsListE but fails in the case an error is returned
func VnetSubnetsList(t *testing.T, subscriptionID string, resourceGroupName string, vnetName string) []string {
subnets, err := VnetSubnetsListE(subscriptionID, resourceGroupName, vnetName)
if err != nil {
t.Fatal(err)
}
return subnets
}

0 comments on commit 1395c9d

Please sign in to comment.