Skip to content

Commit 395de04

Browse files
authored
Stop using the internal reset credentials in the serverless provider (#2307)
Stop using the internal `_reset-internal-credentials` API to obtain the credentials used for serverless stacks managed by elastic-package. This API is only available to Elastic employees. There were two reasons to obtain credentials this way: - Some APIs were restricted in serverless to credentials obtained this way. From these internal APIs, the only one we use now is the one to check the cluster status (`_cluster/health`). In this case, if normal credentials are used, it returns HTTP status 410 (Gone) if the cluster is alive and the credentials are valid. We can consider this as an OK for this case. - At some point during development the project creation API didn't return credentials with enough permissions, so we needed to request them using the reset credentials APIs. Serverless is GA now, and the project creation API returns user and password with admin privileges, what is enough for all elastic-package operations. As these reasons are not strong enough anymore, it would be better to avoid these resets, what will allow to use elastic-package more openly. This is also needed for API keys support (#1633), because API keys neither have access to these internal APIs.
1 parent 2752a24 commit 395de04

File tree

4 files changed

+131
-33
lines changed

4 files changed

+131
-33
lines changed

internal/elasticsearch/client.go

+4
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ func (client *Client) CheckHealth(ctx context.Context) error {
145145
}
146146
defer resp.Body.Close()
147147

148+
if resp.StatusCode == http.StatusGone {
149+
// We are in a managed deployment, API not available, assume healthy.
150+
return nil
151+
}
148152
if resp.StatusCode != http.StatusOK {
149153
return fmt.Errorf("failed to check cluster health: %s", resp.String())
150154
}

internal/elasticsearch/client_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ func TestClusterHealth(t *testing.T) {
6363
// To reproduce the scenario, just start the stack with 8.5 version.
6464
Record: "./testdata/elasticsearch-8-5-healthy",
6565
},
66+
{
67+
// To reproduce the scenario, start a project in serverless, and
68+
// replace the host in the urls with https://127.0.0.1:9200.
69+
Record: "./testdata/elasticsearch-serverless-healthy",
70+
},
6671
{
6772
// To reproduce the scenario, start the stack with 8.5 version and
6873
// limited disk space. If difficult to reproduce, manually modify
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
---
2+
version: 2
3+
interactions:
4+
- id: 0
5+
request:
6+
proto: HTTP/1.1
7+
proto_major: 1
8+
proto_minor: 1
9+
content_length: 0
10+
transfer_encoding: []
11+
trailer: {}
12+
host: ""
13+
remote_addr: ""
14+
request_uri: ""
15+
body: ""
16+
form: {}
17+
headers:
18+
Authorization:
19+
- Basic YWRtaW46cWN5V21PNTM5WTBlOWw5T1lxM3Y1TjIx
20+
User-Agent:
21+
- go-elasticsearch/7.17.10 (linux amd64; Go 1.23.4)
22+
X-Elastic-Client-Meta:
23+
- es=7.17.10,go=1.23.4,t=7.17.10,hc=1.23.4
24+
url: https://127.0.0.1:9200/
25+
method: GET
26+
response:
27+
proto: HTTP/2.0
28+
proto_major: 2
29+
proto_minor: 0
30+
transfer_encoding: []
31+
trailer: {}
32+
content_length: 508
33+
uncompressed: false
34+
body: |
35+
{
36+
"name" : "serverless",
37+
"cluster_name" : "b28743a6426f4b58829f422195a77b1b",
38+
"cluster_uuid" : "RzabjGAWQRCQ0vHoYTrRMA",
39+
"version" : {
40+
"number" : "8.11.0",
41+
"build_flavor" : "serverless",
42+
"build_type" : "docker",
43+
"build_hash" : "00000000",
44+
"build_date" : "2023-10-31",
45+
"build_snapshot" : false,
46+
"lucene_version" : "9.7.0",
47+
"minimum_wire_compatibility_version" : "8.11.0",
48+
"minimum_index_compatibility_version" : "8.11.0"
49+
},
50+
"tagline" : "You Know, for Search"
51+
}
52+
headers:
53+
Content-Length:
54+
- "508"
55+
Content-Type:
56+
- application/json
57+
Date:
58+
- Tue, 24 Dec 2024 16:55:35 GMT
59+
Elastic-Api-Version:
60+
- "2023-10-31"
61+
X-Cloud-Request-Id:
62+
- OcEBAr_LQMioTlvn_pbkIQ
63+
X-Elastic-Product:
64+
- Elasticsearch
65+
X-Found-Handling-Cluster:
66+
- b28743a6426f4b58829f422195a77b1b.es
67+
X-Found-Handling-Instance:
68+
- es-es-search-7b77d558d4-pv8xf
69+
status: 200 OK
70+
code: 200
71+
duration: 5.561667976s
72+
- id: 1
73+
request:
74+
proto: HTTP/1.1
75+
proto_major: 1
76+
proto_minor: 1
77+
content_length: 0
78+
transfer_encoding: []
79+
trailer: {}
80+
host: ""
81+
remote_addr: ""
82+
request_uri: ""
83+
body: ""
84+
form: {}
85+
headers:
86+
Authorization:
87+
- Basic YWRtaW46cWN5V21PNTM5WTBlOWw5T1lxM3Y1TjIx
88+
User-Agent:
89+
- go-elasticsearch/7.17.10 (linux amd64; Go 1.23.4)
90+
X-Elastic-Client-Meta:
91+
- es=7.17.10,go=1.23.4,t=7.17.10,hc=1.23.4
92+
url: https://127.0.0.1:9200/_cluster/health
93+
method: GET
94+
response:
95+
proto: HTTP/2.0
96+
proto_major: 2
97+
proto_minor: 0
98+
transfer_encoding: []
99+
trailer: {}
100+
content_length: 363
101+
uncompressed: false
102+
body: '{"error":{"root_cause":[{"type":"api_not_available_exception","reason":"Request for uri [/_cluster/health] with method [GET] exists but is not available when running in serverless mode"}],"type":"api_not_available_exception","reason":"Request for uri [/_cluster/health] with method [GET] exists but is not available when running in serverless mode"},"status":410}'
103+
headers:
104+
Content-Length:
105+
- "363"
106+
Content-Type:
107+
- application/json
108+
Date:
109+
- Tue, 24 Dec 2024 16:55:35 GMT
110+
Elastic-Api-Version:
111+
- "2023-10-31"
112+
X-Cloud-Request-Id:
113+
- z0crFf48SH6oYcdTJWoptQ
114+
X-Elastic-Product:
115+
- Elasticsearch
116+
X-Found-Handling-Cluster:
117+
- b28743a6426f4b58829f422195a77b1b.es
118+
X-Found-Handling-Instance:
119+
- es-es-search-7b77d558d4-pv8xf
120+
status: 410 Gone
121+
code: 410
122+
duration: 129.604829ms

internal/serverless/client.go

-33
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,6 @@ func (c *Client) CreateProject(ctx context.Context, name, region, projectType st
171171
return nil, fmt.Errorf("error while decoding create project response: %w", err)
172172
}
173173

174-
err = c.ResetCredentials(ctx, serverlessProject)
175-
if err != nil {
176-
return nil, fmt.Errorf("failed to reset credentials: %w", err)
177-
}
178-
179174
return serverlessProject, nil
180175
}
181176

@@ -230,34 +225,6 @@ func (c *Client) StatusProject(ctx context.Context, project *Project) (string, e
230225
return status.Phase, nil
231226
}
232227

233-
func (c *Client) ResetCredentials(ctx context.Context, project *Project) error {
234-
resourcePath, err := url.JoinPath(c.host, projectsAPI, project.Type, project.ID, "_reset-internal-credentials")
235-
if err != nil {
236-
return fmt.Errorf("could not build the URL: %w", err)
237-
}
238-
statusCode, respBody, err := c.post(ctx, resourcePath, nil)
239-
if err != nil {
240-
return fmt.Errorf("error creating project: %w", err)
241-
}
242-
243-
if statusCode != http.StatusOK {
244-
return fmt.Errorf("unexpected status code %d", statusCode)
245-
}
246-
247-
var credentials struct {
248-
Username string `json:"username"`
249-
Password string `json:"password"`
250-
}
251-
if err := json.Unmarshal(respBody, &credentials); err != nil {
252-
return fmt.Errorf("unable to decode credentials: %w", err)
253-
}
254-
255-
project.Credentials.Username = credentials.Username
256-
project.Credentials.Password = credentials.Password
257-
258-
return nil
259-
}
260-
261228
func (c *Client) DeleteProject(ctx context.Context, project *Project) error {
262229
resourcePath, err := url.JoinPath(c.host, projectsAPI, project.Type, project.ID)
263230
if err != nil {

0 commit comments

Comments
 (0)