-
Notifications
You must be signed in to change notification settings - Fork 110
/
Copy pathframework.go
241 lines (214 loc) · 9.09 KB
/
framework.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
package provider
import (
"context"
"crypto/tls"
"fmt"
"os"
"strings"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
datasource_artifact "github.com/jfrog/terraform-provider-artifactory/v12/pkg/artifactory/datasource/artifact"
datasource_repository "github.com/jfrog/terraform-provider-artifactory/v12/pkg/artifactory/datasource/repository"
"github.com/jfrog/terraform-provider-artifactory/v12/pkg/artifactory/resource/artifact"
"github.com/jfrog/terraform-provider-artifactory/v12/pkg/artifactory/resource/configuration"
"github.com/jfrog/terraform-provider-artifactory/v12/pkg/artifactory/resource/lifecycle"
"github.com/jfrog/terraform-provider-artifactory/v12/pkg/artifactory/resource/replication"
"github.com/jfrog/terraform-provider-artifactory/v12/pkg/artifactory/resource/security"
"github.com/jfrog/terraform-provider-artifactory/v12/pkg/artifactory/resource/user"
"github.com/jfrog/terraform-provider-artifactory/v12/pkg/artifactory/resource/webhook"
"github.com/jfrog/terraform-provider-shared/client"
"github.com/jfrog/terraform-provider-shared/util"
validatorfw_string "github.com/jfrog/terraform-provider-shared/validator/fw/string"
)
// Ensure the implementation satisfies the provider.Provider interface.
var _ provider.Provider = &ArtifactoryProvider{}
type ArtifactoryProvider struct{}
// ArtifactoryProviderModel describes the provider data model.
type ArtifactoryProviderModel struct {
Url types.String `tfsdk:"url"`
AccessToken types.String `tfsdk:"access_token"`
ApiKey types.String `tfsdk:"api_key"`
OIDCProviderName types.String `tfsdk:"oidc_provider_name"`
}
// Metadata satisfies the provider.Provider interface for ArtifactoryProvider
func (p *ArtifactoryProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
resp.TypeName = "artifactory"
resp.Version = Version
}
// Schema satisfies the provider.Provider interface for ArtifactoryProvider.
func (p *ArtifactoryProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"url": schema.StringAttribute{
Description: "Artifactory URL.",
Optional: true,
Validators: []validator.String{
validatorfw_string.IsURLHttpOrHttps(),
},
},
"access_token": schema.StringAttribute{
Description: "This is a access token that can be given to you by your admin under `User Management -> Access Tokens`. If not set, the 'api_key' attribute value will be used.",
Optional: true,
Sensitive: true,
Validators: []validator.String{
stringvalidator.LengthAtLeast(1),
},
},
"api_key": schema.StringAttribute{
Description: "API key. If `access_token` attribute, `JFROG_ACCESS_TOKEN` or `ARTIFACTORY_ACCESS_TOKEN` environment variable is set, the provider will ignore this attribute.",
DeprecationMessage: "An upcoming version will support the option to block the usage/creation of API Keys (for admins to set on their platform).\nIn a future version (scheduled for end of Q3, 2023), the option to disable the usage/creation of API Keys will be available and set to disabled by default. Admins will be able to enable the usage/creation of API Keys.\nBy end of Q4 2024, API Keys will be deprecated all together and the option to use them will no longer be available. See [JFrog API deprecation process](https://jfrog.com/help/r/jfrog-platform-administration-documentation/jfrog-api-key-deprecation-process) for more details.",
Optional: true,
Sensitive: true,
},
"oidc_provider_name": schema.StringAttribute{
Optional: true,
Validators: []validator.String{
stringvalidator.LengthAtLeast(1),
},
Description: "OIDC provider name. See [Configure an OIDC Integration](https://jfrog.com/help/r/jfrog-platform-administration-documentation/configure-an-oidc-integration) for more details.",
},
},
}
}
func (p *ArtifactoryProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
// Check environment variables, first available OS variable will be assigned to the var
url := util.CheckEnvVars([]string{"JFROG_URL", "ARTIFACTORY_URL"}, "")
accessToken := util.CheckEnvVars([]string{"JFROG_ACCESS_TOKEN", "ARTIFACTORY_ACCESS_TOKEN"}, "")
var config ArtifactoryProviderModel
// Read configuration data into model
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
if resp.Diagnostics.HasError() {
return
}
if config.Url.ValueString() != "" {
url = config.Url.ValueString()
}
if url == "" {
resp.Diagnostics.AddError(
"Missing URL Configuration",
"While configuring the provider, the url was not found in "+
"the JFROG_URL/ARTIFACTORY_URL environment variable or provider "+
"configuration block url attribute.",
)
return
}
restyClient, err := client.Build(url, productId)
if err != nil {
resp.Diagnostics.AddError(
"Error creating Resty client",
err.Error(),
)
return
}
oidcAccessToken, err := util.OIDCTokenExchange(ctx, restyClient, config.OIDCProviderName.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Failed OIDC ID token exchange",
err.Error(),
)
return
}
// use token from OIDC provider, which should take precedence over
// environment variable data, if found.
if oidcAccessToken != "" {
accessToken = oidcAccessToken
}
// Check configuration data, which should take precedence over
// environment variable data, if found.
if config.AccessToken.ValueString() != "" {
accessToken = config.AccessToken.ValueString()
}
apiKey := config.ApiKey.ValueString()
if apiKey == "" && accessToken == "" {
resp.Diagnostics.AddError(
"Missing JFrog API key or Access Token",
"While configuring the provider, the API key or Access Token was not found in "+
"the environment variables or provider configuration attributes.",
)
return
}
restyClient, err = client.AddAuth(restyClient, apiKey, accessToken)
if err != nil {
resp.Diagnostics.AddError(
"Error adding Auth to Resty client",
err.Error(),
)
return
}
bypassJFrogTLSVerification := os.Getenv("JFROG_BYPASS_TLS_VERIFICATION")
if strings.ToLower(bypassJFrogTLSVerification) == "true" {
tlsConfig := &tls.Config{
InsecureSkipVerify: true,
}
restyClient.SetTLSClientConfig(tlsConfig)
}
version, err := util.GetArtifactoryVersion(restyClient)
if err != nil {
resp.Diagnostics.AddError(
"Error getting Artifactory version",
fmt.Sprintf("The provider functionality might be affected by the absence of Artifactory version in the context. %v", err),
)
return
}
featureUsage := fmt.Sprintf("Terraform/%s", req.TerraformVersion)
go util.SendUsage(ctx, restyClient.R(), productId, featureUsage)
meta := util.ProviderMetadata{
Client: restyClient,
ProductId: productId,
ArtifactoryVersion: version,
}
resp.DataSourceData = meta
resp.ResourceData = meta
}
// Resources satisfies the provider.Provider interface for ArtifactoryProvider.
func (p *ArtifactoryProvider) Resources(ctx context.Context) []func() resource.Resource {
return []func() resource.Resource{
artifact.NewArtifactResource,
artifact.NewItemPropertiesResource,
user.NewAnonymousUserResource,
user.NewManagedUserResource,
user.NewUnmanagedUserResource,
user.NewUserResource,
security.NewGroupResource,
security.NewScopedTokenResource,
security.NewGlobalEnvironmentResource,
security.NewDistributionPublicKeyResource,
security.NewCertificateResource,
security.NewKeyPairResource,
security.NewPasswordExpirationPolicyResource,
security.NewUserLockPolicyResource,
security.NewVaultConfigurationResource,
configuration.NewLdapSettingResource,
configuration.NewLdapGroupSettingResource,
configuration.NewBackupResource,
configuration.NewGeneralSecurityResource,
configuration.NewMailServerResource,
configuration.NewPackageCleanupPolicyResource,
configuration.NewPropertySetResource,
configuration.NewProxyResource,
configuration.NewRepositoryLayoutResource,
lifecycle.NewReleaseBundleV2Resource,
lifecycle.NewReleaseBundleV2PromotionResource,
replication.NewLocalRepositorySingleReplicationResource,
replication.NewLocalRepositoryMultiReplicationResource,
replication.NewRemoteRepositoryReplicationResource,
webhook.NewArtifactWebhookResource,
}
}
// DataSources satisfies the provider.Provider interface for ArtifactoryProvider.
func (p *ArtifactoryProvider) DataSources(_ context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{
datasource_repository.NewRepositoriesDataSource,
datasource_artifact.NewFileListDataSource,
}
}
func Framework() func() provider.Provider {
return func() provider.Provider {
return &ArtifactoryProvider{}
}
}