From 26eb2c104a7d0281dfcffb2c31cb6faaaf321a90 Mon Sep 17 00:00:00 2001 From: Tobias Trabelsi Date: Tue, 21 Jun 2022 23:10:25 +0200 Subject: [PATCH] added ssh key management resource --- Makefile | 4 +- docs/resources/public_key.md | 52 ++++++ examples/.gitignore | 3 +- examples/main.tf | 8 + examples/provider.tf | 2 +- .../resources/gitea_public_key/id_ed25519.pub | 1 + .../resources/gitea_public_key/resource.tf | 14 ++ gitea/provider.go | 1 + gitea/resource_gitea_public_key.go | 155 ++++++++++++++++++ 9 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 docs/resources/public_key.md create mode 100644 examples/resources/gitea_public_key/id_ed25519.pub create mode 100644 examples/resources/gitea_public_key/resource.tf create mode 100644 gitea/resource_gitea_public_key.go diff --git a/Makefile b/Makefile index 7838040..2761112 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ GOFMT_FILES?=$$(find . -name '*.go' |grep -v vendor) GOFMT ?= gofmt -s -VERSION = 0.4.0 +VERSION = 0.5.0 test: fmt-check go test -i $(TEST) || exit 1 @@ -37,3 +37,5 @@ install: build @echo ~/.terraform.d/plugins/terraform.local/lerentis/gitea/${VERSION}/linux_amd64/terraform-provider-gitea_${VERSION} @mkdir -p ~/.terraform.d/plugins/terraform.local/lerentis/gitea/${VERSION}/linux_amd64 @mv terraform-provider-gitea_${VERSION} ~/.terraform.d/plugins/terraform.local/lerentis/gitea/${VERSION}/linux_amd64/terraform-provider-gitea_${VERSION} +doc: + tfplugindocs \ No newline at end of file diff --git a/docs/resources/public_key.md b/docs/resources/public_key.md new file mode 100644 index 0000000..aba61fc --- /dev/null +++ b/docs/resources/public_key.md @@ -0,0 +1,52 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "gitea_public_key Resource - terraform-provider-gitea" +subcategory: "" +description: |- + gitea_public_key manages ssh key that are associated with users. +--- + +# gitea_public_key (Resource) + +`gitea_public_key` manages ssh key that are associated with users. + +## Example Usage + +```terraform +resource "gitea_user" "test" { + username = "test" + login_name = "test" + password = "Geheim1!" + email = "test@user.dev" + must_change_password = false +} + + +resource "gitea_public_key" "test_user_key" { + title = "test" + key = file("${path.module}/id_ed25519.pub") + username = gitea_user.test.username +} +``` + + +## Schema + +### Required + +- `key` (String, Sensitive) An armored SSH key to add +- `title` (String) Title of the key to add +- `username` (String) User to associate with the added key + +### Optional + +- `read_only` (Boolean) Describe if the key has only read access or read/write + +### Read-Only + +- `created` (String) +- `fingerprint` (String) +- `id` (String) The ID of this resource. +- `type` (String) + + diff --git a/examples/.gitignore b/examples/.gitignore index 2674ee4..85b87b4 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -2,4 +2,5 @@ .terraform.lock.hcl terraform.tfstate terraform.tfstate.backup -*.tfvars \ No newline at end of file +*.tfvars +id_ed25519 \ No newline at end of file diff --git a/examples/main.tf b/examples/main.tf index 6712d8a..c511e41 100644 --- a/examples/main.tf +++ b/examples/main.tf @@ -38,3 +38,11 @@ resource "gitea_user" "test" { must_change_password = false admin = true } + + +resource "gitea_public_key" "test_user_key" { + title = "test" + key = file("${path.module}/resources/gitea_public_key/id_ed25519.pub") + read_only = true + username = gitea_user.test.username +} diff --git a/examples/provider.tf b/examples/provider.tf index cd5336b..44cdeef 100644 --- a/examples/provider.tf +++ b/examples/provider.tf @@ -2,7 +2,7 @@ terraform { required_providers { gitea = { source = "terraform.local/lerentis/gitea" - version = "0.4.0" + version = "0.5.0" } } } diff --git a/examples/resources/gitea_public_key/id_ed25519.pub b/examples/resources/gitea_public_key/id_ed25519.pub new file mode 100644 index 0000000..a6f4571 --- /dev/null +++ b/examples/resources/gitea_public_key/id_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINn6hAP48oKz6MVWjYvn0fne2YeaOv/zC6zuvFXlJKf2 test@dev.local diff --git a/examples/resources/gitea_public_key/resource.tf b/examples/resources/gitea_public_key/resource.tf new file mode 100644 index 0000000..1862438 --- /dev/null +++ b/examples/resources/gitea_public_key/resource.tf @@ -0,0 +1,14 @@ +resource "gitea_user" "test" { + username = "test" + login_name = "test" + password = "Geheim1!" + email = "test@user.dev" + must_change_password = false +} + + +resource "gitea_public_key" "test_user_key" { + title = "test" + key = file("${path.module}/id_ed25519.pub") + username = gitea_user.test.username +} diff --git a/gitea/provider.go b/gitea/provider.go index bc00644..643bbc0 100644 --- a/gitea/provider.go +++ b/gitea/provider.go @@ -79,6 +79,7 @@ func Provider() terraform.ResourceProvider { "gitea_user": resourceGiteaUser(), "gitea_oauth2_app": resourceGiteaOauthApp(), "gitea_repository": resourceGiteaRepository(), + "gitea_public_key": resourceGiteaPublicKey(), }, ConfigureFunc: providerConfigure, diff --git a/gitea/resource_gitea_public_key.go b/gitea/resource_gitea_public_key.go new file mode 100644 index 0000000..611f4b9 --- /dev/null +++ b/gitea/resource_gitea_public_key.go @@ -0,0 +1,155 @@ +package gitea + +import ( + "fmt" + "strconv" + + "code.gitea.io/sdk/gitea" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +const ( + PublicKeyUser string = "username" + PublicKey string = "key" + PublicKeyReadOnlyFlag string = "read_only" + PublicKeyTitle string = "title" + PublicKeyId string = "id" + PublicKeyFingerprint string = "fingerprint" + PublicKeyCreated string = "created" + PublicKeyType string = "type" +) + +func resourcePublicKeyRead(d *schema.ResourceData, meta interface{}) (err error) { + client := meta.(*gitea.Client) + + id, err := strconv.ParseInt(d.Id(), 10, 64) + + var resp *gitea.Response + var pubKey *gitea.PublicKey + + pubKey, resp, err = client.GetPublicKey(id) + + if err != nil { + if resp.StatusCode == 404 { + d.SetId("") + return nil + } else { + return err + } + } + + err = setPublicKeyResourceData(pubKey, d) + + return +} + +func resourcePublicKeyCreate(d *schema.ResourceData, meta interface{}) (err error) { + client := meta.(*gitea.Client) + + var pubKey *gitea.PublicKey + + opts := gitea.CreateKeyOption{ + Title: d.Get(PublicKeyTitle).(string), + Key: d.Get(PublicKey).(string), + ReadOnly: d.Get(PublicKeyReadOnlyFlag).(bool), + } + + pubKey, _, err = client.AdminCreateUserPublicKey(d.Get(PublicKeyUser).(string), opts) + + err = setPublicKeyResourceData(pubKey, d) + + return +} + +func resourcePublicKeyUpdate(d *schema.ResourceData, meta interface{}) (err error) { + // update = recreate + resourcePublicKeyDelete(d, meta) + resourcePublicKeyCreate(d, meta) + return +} + +func resourcePublicKeyDelete(d *schema.ResourceData, meta interface{}) (err error) { + client := meta.(*gitea.Client) + + id, err := strconv.ParseInt(d.Id(), 10, 64) + + var resp *gitea.Response + + resp, err = client.AdminDeleteUserPublicKey(d.Get(PublicKeyUser).(string), int(id)) + + if err != nil { + if resp.StatusCode == 404 { + return + } else { + return err + } + } + + return +} + +func setPublicKeyResourceData(pubKey *gitea.PublicKey, d *schema.ResourceData) (err error) { + d.SetId(fmt.Sprintf("%d", pubKey.ID)) + d.Set(PublicKeyUser, pubKey.Owner.UserName) + d.Set(PublicKey, pubKey.Key) + d.Set(PublicKeyTitle, pubKey.Title) + d.Set(PublicKeyReadOnlyFlag, pubKey.ReadOnly) + d.Set(PublicKeyCreated, pubKey.Created) + d.Set(PublicKeyFingerprint, pubKey.Fingerprint) + d.Set(PublicKeyType, pubKey.KeyType) + return +} + +func resourceGiteaPublicKey() *schema.Resource { + return &schema.Resource{ + Read: resourcePublicKeyRead, + Create: resourcePublicKeyCreate, + Update: resourcePublicKeyUpdate, + Delete: resourcePublicKeyDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "title": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Title of the key to add", + }, + "key": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Sensitive: true, + Description: "An armored SSH key to add", + }, + "read_only": { + Type: schema.TypeBool, + Required: false, + Optional: true, + Default: false, + Description: "Describe if the key has only read access or read/write", + }, + "username": { + Type: schema.TypeString, + Required: true, + Optional: false, + ForceNew: true, + Description: "User to associate with the added key", + }, + "fingerprint": { + Type: schema.TypeString, + Computed: true, + }, + "created": { + Type: schema.TypeString, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + }, + Description: "`gitea_public_key` manages ssh key that are associated with users.", + } +}