Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
Whitelister
Whitelister
.vscode
.idea
22 changes: 22 additions & 0 deletions configs/testConfigs/configWithIncorrectFilterTypeAzure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
syncInterval: 10s
filter:
filterType: InCorrectType
labelName: whitelister
labelValue: true
ipProviders:
- name: kubernetes
params:
FromPort: 0
ToPort: 65535
IpProtocol: tcp
provider:
name: azure
params:
KeepRuleDescriptionPrefix: "DO NOT REMOVE -"
RemoveRule: true
SubscriptionID: "47c9180a-967d-4ba0-bfc0-7b12762f0779"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not real values right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes these are dummy

ClientID: "4ab0b7f2-197f-4b14-bf22-1856a6f095aa"
ClientSecret: "thisisthesecret"
TenantID: "73cf1f9c-03d0-4709-8434-b50bc8440454"
ResourceGroupName: "my-resource-group"

23 changes: 23 additions & 0 deletions configs/testConfigs/correctAzureGitConfigWithSG.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
syncInterval: 10s
filter:
filterType: SecurityGroup
labelName: whitelister
labelValue: true
ipProviders:
- name: git
params:
AccessToken: "access-token"
URL: "http://github.com/stakater/whitelister-config.git"
Config: "config.yaml"
provider:
name: azure
params:
KeepRuleDescriptionPrefix: "DO NOT REMOVE -"
RemoveRule: true
SubscriptionID: "47c9180a-967d-4ba0-bfc0-7b12762f0779"
ClientID: "4ab0b7f2-197f-4b14-bf22-1856a6f095aa"
ClientSecret: "thisisthesecret"
TenantID: "73cf1f9c-03d0-4709-8434-b50bc8440454"
ResourceGroupName: "my-resource-group"


7 changes: 5 additions & 2 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ provider:

## Filter

labelName and labelValue represent the key value pair of a tag in case of filterType "SecurityGroup". However, if filterType is "LoadBalancer" labelName and labelValue correspond to the label's key value pair on kubernetes service
labelName and labelValue represent the key value pair of a tag in case of filterType "SecurityGroup". However, if filterType is "LoadBalancer" labelName and labelValue correspond to the label's key value pair on kubernetes service.

Azure supports only "SecurityGroup" filter type.

## Ip Providers

Expand All @@ -56,4 +58,5 @@ Whitelister supports the following IP Providers

Whitelister supports the following Providers

1. [Amazon Web Services](providers/aws.md)
1. [Amazon Web Services](providers/aws.md)
2. [Azure](providers/azure.md)
16 changes: 16 additions & 0 deletions docs/providers/azure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Azure

Azure can be used as a cloud provider where your servers reside. The current provider can add a list of IP rules to the security group and optionally remove previously added security rules. If you wish to keep some of the hard coded rules then you can add a certain prefix to their description and Whitelister will not remove them.

## Configuration

Azure provider supports the following configuration

|Key |Status |Description|
|----------|--------|-----------|
|SubscriptionID |required|The subscription ID is a unique uuid string that identifies the Azure subscription|
|ClientID |required|ID required to connect to Azure|
|ClientSecret |required|Secret used for establishing connection with Azure|
|TenantID |required|Unique identifier of the Azure active directory instance|
|RemoveRule|required|Whether to remove un-recognized rules or not. Accepts `true` or `false`|
|KeepRuleDescriptionPrefix|optional|A string value, which when found as a prefix in the description of a security rule then the security rule is not removed|
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ module github.com/stakater/Whitelister
go 1.14

require (
github.com/Azure/azure-sdk-for-go v45.1.0+incompatible
github.com/Azure/go-autorest/autorest v0.11.0
github.com/Azure/go-autorest/autorest/azure/auth v0.5.0
github.com/Azure/go-autorest/autorest/to v0.4.0
github.com/Azure/go-autorest/autorest/validation v0.3.0 // indirect
github.com/aws/aws-sdk-go v1.33.5
github.com/go-delve/delve v1.5.0 // indirect
github.com/imdario/mergo v0.3.9 // indirect
github.com/mitchellh/mapstructure v1.3.2
github.com/sirupsen/logrus v1.6.0
Expand Down
64 changes: 64 additions & 0 deletions go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion internal/pkg/cmd/Whitelister.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
func NewWhitelisterCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "Whitelister",
Short: "A tool which manages AWS security groups to allow access to nodes and developers",
Short: "A tool which manages AWS and Azure security groups to allow access to nodes and developers",
Run: startWhitelister,
}
return cmd
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/cmd/Whitelister_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestGetWhiteListerCommand(t *testing.T) {
name: "Get Cobra Command",
want: &cobra.Command{
Use: "Whitelister",
Short: "A tool which manages AWS security groups to allow access to nodes and developers",
Short: "A tool which manages AWS and Azure security groups to allow access to nodes and developers",
Run: startWhitelister,
},
},
Expand Down
41 changes: 41 additions & 0 deletions internal/pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,53 @@ func TestReadConfig(t *testing.T) {
},
wantErr: false,
},
{
name: "TestingWithCorrectValuesForSecurityGroupFilterOnAzure",
args: args{filePath: configFilePath + "correctAzureGitConfigWithSG.yaml"},
want: Config{
SyncInterval: "10s",
IpProviders: []IpProvider{
{
Name: "git",
Params: map[interface{}]interface{}{
"AccessToken": "access-token",
"URL": "http://github.com/stakater/whitelister-config.git",
"Config": "config.yaml",
},
},
},
Provider: Provider{
Name: "azure",
Params: map[interface{}]interface{}{
"RemoveRule": true,
"KeepRuleDescriptionPrefix": "DO NOT REMOVE -",
"SubscriptionID": "47c9180a-967d-4ba0-bfc0-7b12762f0779",
"ClientID": "4ab0b7f2-197f-4b14-bf22-1856a6f095aa",
"ClientSecret": "thisisthesecret",
"TenantID": "73cf1f9c-03d0-4709-8434-b50bc8440454",
"ResourceGroupName": "my-resource-group",
},
},
Filter: Filter{
FilterType: SecurityGroup,
LabelName: "whitelister",
LabelValue: "true",
},
},
wantErr: false,
},
{
name: "TestingWithIncorrectFilterType",
args: args{filePath: configFilePath + "configWithIncorrectFilterType.yaml"},
wantErr: true,
errValue: errors.New("incorrect FilterType :InCorrectType provided"),
},
{
name: "TestingWithIncorrectFilterTypeAzure",
args: args{filePath: configFilePath + "configWithIncorrectFilterTypeAzure.yaml"},
wantErr: true,
errValue: errors.New("incorrect FilterType :InCorrectType provided"),
},
{
name: "TestingWithEmptyFile",
args: args{filePath: configFilePath + "Empty.yaml"},
Expand Down
75 changes: 75 additions & 0 deletions internal/pkg/providers/azure/azure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package azure

import (
"github.com/Azure/azure-sdk-for-go/profiles/2019-03-01/network/mgmt/network"
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-05-01/resources"
"github.com/Azure/go-autorest/autorest"

"github.com/mitchellh/mapstructure"
"github.com/sirupsen/logrus"
"github.com/stakater/Whitelister/internal/pkg/config"
clientset "k8s.io/client-go/kubernetes"

"github.com/stakater/Whitelister/internal/pkg/utils"
)

// Azure provider class implementing the Provider interface
type Azure struct {
ClientSet clientset.Interface
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe keep clients in this structure instead of credentials? e.g securityRulesClient, securityGroupClient etc. Then we don't need to create new clients on each reconcile loop.

resourcesClient resources.Client
securityGroupClient network.SecurityGroupsClient
securityRulesClient network.SecurityRulesClient
authorizer autorest.Authorizer
SubscriptionID string
ClientID string
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not keep fields that will not be used in future in this structure, e.g ClientID, ClientSecret, TenantID and subscriptionID.

ClientSecret string
TenantID string
ResourceGroupName string
RemoveRule bool
KeepRuleDescriptionPrefix string
}

// GetName Returns name of provider
func (a *Azure) GetName() string {
return "Azure"
}

// Init initializes the Azure Provider Configuration like client id and client secret
func (a *Azure) Init(params map[interface{}]interface{}, clientSet clientset.Interface) error {
err := mapstructure.Decode(params, &a) //Converts the params to Azure struct fields
if err != nil {
return err
}

err = a.initializeAzureClients() // initializes azure clients for whitelisting ips
if err != nil {
return err
}

return nil
}

// WhiteListIps - Get List of IP addresses to whitelist
func (a *Azure) WhiteListIps(filter config.Filter, ipPermissions []utils.IpPermission) error {

resources, err := a.fetchResources(filter)
if err != nil {
logrus.Error("Error fetching resources for the given filter")
return err
}

for _, resource := range resources {
logrus.Infof("Name of the security group %s", *resource.Name)
securityGroup, err := a.fetchSecurityGroup(*resource.Name)
if err != nil {
logrus.Errorf("Error fetching security group for resource %s", *resource.Name)
return err
}
err = a.updateSecurityRules(*securityGroup, ipPermissions)
if err != nil {
logrus.Errorf("Error whitelisting ips for security group %s", *resource.Name)
return err
}
}
return nil
}
Loading