Terraform permet à DoorDash de gérer de manière programmatique certains accès à travers notre infrastructure. Cependant, l'absence d'un Terraform pour Splunkl'outil que nous utilisons pour rechercher, analyser et visualiser nos données, rendait difficile la gestion programmatique et à grande échelle de l'accès des utilisateurs.
L'efficacité et la sécurité obtenues par l'intégration de l'accès via Terraform nous ont amenés à créer un fournisseur Terraform pour Splunk.
Les fournisseurs Terraform, qui comprennent actuellement des produits aussi divers qu'Akamai, Github et MySQL, intègrent des services à Terraform. Avant de créer notre fournisseur Terraform pour Splunk, nous devions gérer l'accès à Splunk séparément, un processus qui demandait plus de travail aux administrateurs sans pour autant améliorer la sécurité des données.
Nous avons conclu que l'écriture d'un nouveau fournisseur Terraform pour Splunk valait la peine pour DoorDash, et que le processus valait la peine d'être documenté pour la communauté des ingénieurs dans son ensemble. Terraform fournit un moyen flexible et facile de gérer les services existants et personnalisés, comme nous le verrons dans ce billet. De plus, nous avons l'intention de mettre en open source notre fournisseur Terraform afin que d'autres organisations puissent bénéficier de ce travail et gérer une infrastructure plus efficace et plus sûre.
Que sont les fournisseurs Terraform personnalisés ?
Terraform est un outil populaire utilisé pour construire, modifier et gérer l'infrastructure d'une manière sûre et reproductible en utilisant des fichiers pour la configuration au lieu de modifier manuellement les paramètres du service.
Terraform est logiquement divisé en deux parties : Terraform Core et Terraform Plugins :
Le composant Terraform Core communique avec les plugins à l'aide de RPC (remote procedure calls) et est responsable de la découverte et du chargement des plugins.
Le composant Terraform Plugins fournit un mécanisme de gestion d'un service spécifique (c'est-à-dire Splunk, dans cet article). Ces plugins spécifiques à un service sont connus sous le nom de fournisseurs Terraform personnalisés.
Les principales responsabilités des fournisseurs Terraform personnalisés sont les suivantes :
- Initialisation de toutes les bibliothèques incluses utilisées pour effectuer des appels à l'API
- Authentification auprès du fournisseur d'infrastructure
- Définition des ressources correspondant à des services spécifiques
Chaque fournisseur Terraform peut gérer une ou plusieurs ressources. Une ressource représente un composant au sein du fournisseur qui possède un ensemble d'attributs configurables et une fonction de CRUD (création, lecture, mise à jour, suppression).
Bien qu'il soit possible d'écrire un plugin dans un autre langage, presque tous les plugins Terraform sont écrits en Go afin de tirer parti des bibliothèques d'aide fournies par bibliothèques d'aide fournies par Terraform. Ces plugins sont ensuite distribués sous la forme de binaires Go.
Comment écrire un fournisseur Terraform personnalisé ?
Comme nous l'avons vu dans la section précédente, les fournisseurs Terraform personnalisés ne sont rien de plus que des binaires Go écrits pour gérer certaines ressources au sein d'un service. Dans cette section, nous allons vous guider pas à pas dans la création de votre propre fournisseur Terraform.
Avant de commencer, assurez-vous que vous avez accès à une bibliothèque client API pour la gestion des rôles Splunk et de la technologie SAML et les groupes SAML. Selon la documentation de Terraform'Äôs documentationLa logique de la bibliothèque client ne doit pas être implémentée dans le fournisseur. Au lieu de cela, Terraform devrait consommer une bibliothèque client indépendante qui implémente la logique de base pour communiquer en amont.
Vous trouverez ci-dessous les étapes à suivre pour créer votre propre fournisseur Terraform :
- Définir le point d'entrée du fournisseur.
- Définir le fournisseur lui-même.
- Définir les ressources que le fournisseur contrôlera.
- Construire et tester le binaire du plugin Terraform
Le cadre Terraform gère automatiquement toutes les opérations des fournisseurs une fois qu'ils sont définis. Ces composants utilisent une bibliothèque d'aide fournie par Terraform, la bibliothèque d'aide fournie par Terraform, qui offre une interface de haut niveau pour écrire des fournisseurs de ressources dans Terraform.
Définition du point d'entrée du fournisseur
La première étape de la création d'un fournisseur Terraform personnalisé consiste à définir le point d'entrée du fournisseur. Comme indiqué ci-dessus, les fournisseurs Terraform personnalisés sont distribués sous forme de binaires Go. Terraform exige que chacun de ces binaires soit préfixé par 'Äúterraform-provider-'Äù. Ainsi, lorsque nous créons un répertoire dans notre GOPATH, il doit être nommé 'Äúterraform-provider-splunk'Äù. À l'intérieur de ce répertoire GOPATH, nous spécifions le point d'entrée de notre fournisseur dans le fichier main.go. Vous trouverez ci-dessous un exemple de code qui démontre ce point d'entrée vers le fournisseur.
package main
import (
splunkplugin "github.com/doordash/terraform-provider-splunk/splunk"
"github.com/hashicorp/terraform-plugin-sdk/plugin"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: func() terraform.ResourceProvider {
return splunkplugin.Provider()
},
})
}
L'exemple de code ci-dessus montre que trois bibliothèques sont importées dans le fichier main.go - deux d'entre elles sont des bibliothèques standard et la troisième est une bibliothèque personnalisée. Voici les deux bibliothèques standard :
- 'Äúgithub.com/hashicorp/terraform-plugin-sdk/plugin'Äù library : qui agit comme le serveur gRPC du fournisseur Terraform. Elle exécute toute logique de ressource basée sur la configuration analysée reçue et fournit au Terraform Core l'état mis à jour d'une ressource ou un retour d'information approprié sous la forme d'une validation ou d'autres erreurs.
- 'Äúgithub.com/hashicorp/terraform-plugin-sdk/terraform'Äù library : cette interface doit être mise en œuvre par tout fournisseur de ressources. Elle crée et gère les ressources dans une configuration Terraform.
La bibliothèque personnalisée contient la mise en œuvre du fournisseur, que nous aborderons dans la section suivante.
Définition du fournisseur lui-même
Dans cette section, nous aborderons les détails de la mise en œuvre du fournisseur. Un fournisseur est chargé de comprendre les interactions de l'API avec un service et d'exposer ses ressources. Le point de départ du fournisseur ainsi que toutes ses propriétés sont définis dans cette section. Ces propriétés sont utilisées pour initialiser le client de l'API, déclarer les ressources qui seront contrôlées et définir tous les détails de configuration. Ces propriétés peuvent comprendre les éléments suivants
- Schema : Il s'agit d'un schéma facultatif pour la configuration de ce fournisseur. La bibliothèque standard helper schema est utilisée pour définir le schéma du fournisseur.
- ResourceMap : Cette propriété déclare la liste des ressources disponibles que ce fournisseur va gérer.
- ConfigureFunc : Il s'agit d'une fonction facultative permettant de configurer le fournisseur. Elle peut être utilisée pour s'authentifier auprès du service.
import (
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func Provider() *schema.Provider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"hostname": &schema.Schema{...
},
"port": &schema.Schema{...
},
"username": &schema.Schema{...
},
"password": &schema.Schema{...
},
},
ResourcesMap: map[string]*schema.Resource{
"splunk_role": resourceRole(),
"splunk_saml_group": resourceSamlGroup(),
},
ConfigureFunc: providerConfigure,
}
}
Définir les ressources que le fournisseur contrôle
Dans cette section, nous allons définir les ressources Splunk et leurs attributs que nous voulons que le fournisseur contrôle, c'est-à-dire les rôles Splunk et les groupes SAML Splunk. Les rôles Splunk déterminent le niveau d'accès que les utilisateurs peuvent avoir et les tâches qu'ils peuvent effectuer, tandis que les groupes SAML Splunk permettent aux groupes autorisés sur votre serveur SAML de se connecter à votre instance Splunk. Un composant majeur de l'authentification et de l'autorisation Splunk est géré par ces deux ressources et leurs attributs, que nous définirons ci-dessous.
Le schéma de ressources de la bibliothèque d'assistance fournit une abstraction qui nous permet de gérer uniquement les opérations CRUD tout en déchargeant cette bibliothèque d'opérations telles que la validation et la génération de différences.
Chaque ressource se compose des éléments suivants :
1) Définir les fonctions de création, de lecture, de mise à jour et de suppression.
- Chaque définition de fonction se voit transmettre les données de ressources du schéma
- Les fonctions de création et de mise à jour définissent l'ID des données de la ressource (à l'aide de SetIId). Un ID non vide indique à Terraform qu'une ressource a été créée et est une valeur utilisée pour relire la ressource.
- La fonction de suppression définit l'ID comme une chaîne de caractères vierge
func resourceRoleDelete(d *schema.ResourceData, m interface{}) error {
apiClient := m.(*splunkclient.Client)
err := apiClient.DeleteRole(d.Get("rolename").(string))
if err != nil {
return err
}
d.SetId("")
return nil
}
2) Schéma de la ressource : les attributs de la ressource. Pour chaque attribut, vous pouvez définir les éléments suivants (entre autres) :
- ForceNew : supprimer et recréer une ressource.
- Obligatoire/facultatif
- Type
- Description
- Défaut
import (
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func resourceRole() *schema.Resource {
return &schema.Resource{
Create: resourceRoleCreate,
Read: resourceRoleRead,
Update: resourceRoleUpdate,
Delete: resourceRoleDelete,
Schema: map[string]*schema.Schema{
"rolename": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "The name of the role, also acts as its unique ID. Required.",
ForceNew: true,
},
"capabilities": &schema.Schema{...
},
"cumulativertsrchjobsquota": &schema.Schema{...
},
"cumulativesrchjobsquota": &schema.Schema{...
},
"defaultapp": &schema.Schema{...
},
"srchindexesallowed": &schema.Schema{...
},
"srchindexesdefault": &schema.Schema{...
},
"srchjobsquota": &schema.Schema{...
},
"rtsrchjobsquota": &schema.Schema{...
},
"srchdiskquota": &schema.Schema{...
},
"srchfilter": &schema.Schema{...
},
"importedroles": &schema.Schema{...
},
},
}
}
Construire et tester le binaire du plugin Terraform
Maintenant que tous les composants de notre fournisseur Terraform personnalisé sont définis, construisons et testons le binaire sur nos machines locales. Construisez le binaire Go (qui est le plugin du fournisseur Terraform) en lançant `go build -o terraform-provider-splunk`. Cette commande produit un binaire nommé `terraform-provider-splunk`.
Pour tester le binaire sur votre machine locale, placez-le dans $HOME/.terraform.d/plugins (pour MacOS) puis suivez les étapes suivantes :
1) Initialiser le fournisseur et définir une ressource SAML Group et une ressource role. Un exemple de fichier Terraform ressemble à l'exemple de code suivant :
provider "splunk" {}
resource "splunk_role" "testrole" {
rolename = "testrole"
capabilities = [
"search"
]
srchindexesallowed = [
"*"
]
srchindexesdefault = [
"test"
]
cumulativertsrchjobsquota = 1
cumulativesrchjobsquota = 2
defaultapp = ""
srchjobsquota = 3
rtsrchjobsquota = 4
srchdiskquota = 5
srchfilter = "*"
}
resource "splunk_saml_group" "test" {
samlgroupname = "testgroup"
rolenames = ["testrole"]
}
2) Initialisez Terraform en lançant `terraform init` puis lancez `terraform plan`. Vous devriez voir la sortie suivante :
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# splunk_role.testrole will be created
+ resource "splunk_role" "testrole" {
+ capabilities = [
+ "search",
]
+ cumulativertsrchjobsquota = 1
+ cumulativesrchjobsquota = 2
+ id = (known after apply)
+ rolename = "testrole"
+ rtsrchjobsquota = 4
+ srchdiskquota = 5
+ srchfilter = "*"
+ srchindexesallowed = [
+ "*",
]
+ srchindexesdefault = [
+ "test",
]
+ srchjobsquota = 3
}
# splunk_saml_group.test will be created
+ resource "splunk_saml_group" "test" {
+ id = (known after apply)
+ rolenames = [
+ "testrole",
]
+ samlgroupname = "testgroup"
}
Plan: 2 to add, 0 to change, 0 to destroy.
3) Appliquer le changement avec `terraform apply`. Ou supprimer le plan local.
Conclusion
Nous espérons que vous avez maintenant une bonne compréhension de la façon de construire un fournisseur Terraform personnalisé pour Splunk. À l'avenir, nous espérons mettre en open source ce fournisseur Splunk Terraform afin qu'il puisse être téléchargé en tant que binaire Go. L'utilisation d'un tel fournisseur aidera votre entreprise à améliorer la visibilité, l'auditabilité et l'évolutivité d'une manière standardisée et sécurisée.
Une fois que vous avez construit et mis en œuvre cette solution, chaque nouveau changement de permission pour un rôle Splunk ainsi que chaque mappage de groupe SAML Splunk peut être effectué par le biais du code. Tous les changements seront suivis. Le provisionnement et le déprovisionnement de ces ressources gérées seront simples et rapides. Toute nouvelle personne prenant en charge la gestion des autorisations Splunk sera en mesure de le faire rapidement et facilement.
En outre, vous pouvez vous appuyer sur les étapes décrites dans cet article pour écrire votre propre fournisseur Terraform pour un autre système.