Skip to content

Commit 9f98aa0

Browse files
committed
Add security label resource
1 parent 8cf2e13 commit 9f98aa0

File tree

4 files changed

+397
-0
lines changed

4 files changed

+397
-0
lines changed

postgresql/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const (
4141
featurePubWithoutTruncate
4242
featureFunction
4343
featureServer
44+
featureSecurityLabel
4445
)
4546

4647
var (
@@ -112,6 +113,8 @@ var (
112113
featureServer: semver.MustParseRange(">=10.0.0"),
113114

114115
featureDatabaseOwnerRole: semver.MustParseRange(">=15.0.0"),
116+
117+
featureSecurityLabel: semver.MustParseRange(">=11.0.0"),
115118
}
116119
)
117120

postgresql/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ func Provider() *schema.Provider {
199199
"postgresql_function": resourcePostgreSQLFunction(),
200200
"postgresql_server": resourcePostgreSQLServer(),
201201
"postgresql_user_mapping": resourcePostgreSQLUserMapping(),
202+
"postgresql_security_label": resourcePostgreSQLSecurityLabel(),
202203
},
203204

204205
DataSourcesMap: map[string]*schema.Resource{
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package postgresql
2+
3+
import (
4+
"bytes"
5+
"database/sql"
6+
"fmt"
7+
"log"
8+
"strings"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
"github.com/lib/pq"
12+
)
13+
14+
const (
15+
securityLabelObjectNameAttr = "object_name"
16+
securityLabelObjectTypeAttr = "object_type"
17+
securityLabelProviderAttr = "label_provider"
18+
securityLabelLabelAttr = "label"
19+
)
20+
21+
func resourcePostgreSQLSecurityLabel() *schema.Resource {
22+
return &schema.Resource{
23+
Create: PGResourceFunc(resourcePostgreSQLSecurityLabelCreate),
24+
Read: PGResourceFunc(resourcePostgreSQLSecurityLabelRead),
25+
Update: PGResourceFunc(resourcePostgreSQLSecurityLabelUpdate),
26+
Delete: PGResourceFunc(resourcePostgreSQLSecurityLabelDelete),
27+
Importer: &schema.ResourceImporter{
28+
StateContext: schema.ImportStatePassthroughContext,
29+
},
30+
31+
Schema: map[string]*schema.Schema{
32+
securityLabelObjectNameAttr: {
33+
Type: schema.TypeString,
34+
Required: true,
35+
ForceNew: true,
36+
Description: "The name of the existing object to apply the security label to",
37+
},
38+
securityLabelObjectTypeAttr: {
39+
Type: schema.TypeString,
40+
Required: true,
41+
ForceNew: true,
42+
Description: "The type of the existing object to apply the security label to",
43+
},
44+
securityLabelProviderAttr: {
45+
Type: schema.TypeString,
46+
Required: true,
47+
ForceNew: true,
48+
Description: "The provider to apply the security label for",
49+
},
50+
securityLabelLabelAttr: {
51+
Type: schema.TypeString,
52+
Required: true,
53+
ForceNew: false,
54+
Description: "The label to be applied",
55+
},
56+
},
57+
}
58+
}
59+
60+
func resourcePostgreSQLSecurityLabelCreate(db *DBConnection, d *schema.ResourceData) error {
61+
if !db.featureSupported(featureSecurityLabel) {
62+
return fmt.Errorf(
63+
"Security Label is not supported for this Postgres version (%s)",
64+
db.version,
65+
)
66+
}
67+
log.Printf("[WARN] PostgreSQL security label Create")
68+
label := d.Get(securityLabelLabelAttr).(string)
69+
if err := resourcePostgreSQLSecurityLabelUpdateImpl(db, d, pq.QuoteLiteral(label)); err != nil {
70+
return err
71+
}
72+
73+
d.SetId(generateSecurityLabelID(d))
74+
75+
return resourcePostgreSQLSecurityLabelReadImpl(db, d)
76+
}
77+
78+
func resourcePostgreSQLSecurityLabelUpdateImpl(db *DBConnection, d *schema.ResourceData, label string) error {
79+
b := bytes.NewBufferString("SECURITY LABEL ")
80+
81+
objectType := d.Get(securityLabelObjectTypeAttr).(string)
82+
objectName := d.Get(securityLabelObjectNameAttr).(string)
83+
provider := d.Get(securityLabelProviderAttr).(string)
84+
fmt.Fprint(b, " FOR ", pq.QuoteIdentifier(provider))
85+
fmt.Fprint(b, " ON ", objectType, pq.QuoteIdentifier(objectName))
86+
fmt.Fprint(b, " IS ", label)
87+
88+
if _, err := db.Exec(b.String()); err != nil {
89+
log.Printf("[WARN] PostgreSQL security label Create failed %s", err)
90+
return err
91+
}
92+
return nil
93+
}
94+
95+
func resourcePostgreSQLSecurityLabelRead(db *DBConnection, d *schema.ResourceData) error {
96+
if !db.featureSupported(featureSecurityLabel) {
97+
return fmt.Errorf(
98+
"Security Label is not supported for this Postgres version (%s)",
99+
db.version,
100+
)
101+
}
102+
log.Printf("[WARN] PostgreSQL security label Read")
103+
104+
return resourcePostgreSQLSecurityLabelReadImpl(db, d)
105+
}
106+
107+
func resourcePostgreSQLSecurityLabelReadImpl(db *DBConnection, d *schema.ResourceData) error {
108+
objectType := d.Get(securityLabelObjectTypeAttr).(string)
109+
objectName := d.Get(securityLabelObjectNameAttr).(string)
110+
provider := d.Get(securityLabelProviderAttr).(string)
111+
112+
txn, err := startTransaction(db.client, "")
113+
if err != nil {
114+
return err
115+
}
116+
defer deferredRollback(txn)
117+
118+
query := "SELECT objtype, objname, provider, label FROM pg_seclabels WHERE objtype = $1 and objname = $2 and provider = $3"
119+
row := db.QueryRow(query, objectType, objectName, provider)
120+
121+
var label string
122+
err = row.Scan(&objectType, &objectName, &provider, &label)
123+
switch {
124+
case err == sql.ErrNoRows:
125+
log.Printf("[WARN] PostgreSQL security label for (%s '%s') with provider %s not found", objectType, objectName, provider)
126+
d.SetId("")
127+
return nil
128+
case err != nil:
129+
return fmt.Errorf("Error reading security label: %w", err)
130+
}
131+
132+
d.Set(securityLabelObjectTypeAttr, objectType)
133+
d.Set(securityLabelObjectNameAttr, objectName)
134+
d.Set(securityLabelProviderAttr, provider)
135+
d.Set(securityLabelLabelAttr, label)
136+
d.SetId(generateSecurityLabelID(d))
137+
138+
return nil
139+
}
140+
141+
func resourcePostgreSQLSecurityLabelDelete(db *DBConnection, d *schema.ResourceData) error {
142+
if !db.featureSupported(featureSecurityLabel) {
143+
return fmt.Errorf(
144+
"Security Label is not supported for this Postgres version (%s)",
145+
db.version,
146+
)
147+
}
148+
log.Printf("[WARN] PostgreSQL security label Delete")
149+
150+
if err := resourcePostgreSQLSecurityLabelUpdateImpl(db, d, "NULL"); err != nil {
151+
return err
152+
}
153+
154+
d.SetId("")
155+
156+
return nil
157+
}
158+
159+
func resourcePostgreSQLSecurityLabelUpdate(db *DBConnection, d *schema.ResourceData) error {
160+
if !db.featureSupported(featureServer) {
161+
return fmt.Errorf(
162+
"Security Label is not supported for this Postgres version (%s)",
163+
db.version,
164+
)
165+
}
166+
log.Printf("[WARN] PostgreSQL security label Update")
167+
168+
label := d.Get(securityLabelLabelAttr).(string)
169+
if err := resourcePostgreSQLSecurityLabelUpdateImpl(db, d, pq.QuoteLiteral(label)); err != nil {
170+
return err
171+
}
172+
173+
return resourcePostgreSQLSecurityLabelReadImpl(db, d)
174+
}
175+
176+
func generateSecurityLabelID(d *schema.ResourceData) string {
177+
return strings.Join([]string{
178+
d.Get(securityLabelProviderAttr).(string),
179+
d.Get(securityLabelObjectTypeAttr).(string),
180+
d.Get(securityLabelObjectNameAttr).(string),
181+
}, ".")
182+
}

0 commit comments

Comments
 (0)