Skip to content

Commit 951d3bf

Browse files
prakashsvmxbexsoftdvaldivia
authored
Inspect API (#1540)
* Inspect API * Address review comments Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com> Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
1 parent 3ae8e14 commit 951d3bf

File tree

10 files changed

+777
-0
lines changed

10 files changed

+777
-0
lines changed

restapi/admin_inspect.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// This file is part of MinIO Console Server
2+
// Copyright (c) 2022 MinIO, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package restapi
18+
19+
import (
20+
"context"
21+
"encoding/binary"
22+
"encoding/hex"
23+
"fmt"
24+
"hash/crc32"
25+
"io"
26+
"io/ioutil"
27+
"net/http"
28+
29+
"github.com/go-openapi/runtime"
30+
"github.com/go-openapi/runtime/middleware"
31+
"github.com/minio/console/models"
32+
"github.com/minio/console/restapi/operations"
33+
"github.com/minio/console/restapi/operations/admin_api"
34+
"github.com/minio/madmin-go"
35+
"github.com/secure-io/sio-go"
36+
)
37+
38+
func registerInspectHandler(api *operations.ConsoleAPI) {
39+
api.AdminAPIInspectHandler = admin_api.InspectHandlerFunc(func(params admin_api.InspectParams, principal *models.Principal) middleware.Responder {
40+
k, r, err := getInspectResult(principal, &params)
41+
isEncryptOn := params.Encrypt != nil && *params.Encrypt
42+
43+
if err != nil {
44+
return admin_api.NewInspectDefault(int(err.Code)).WithPayload(err)
45+
}
46+
47+
return middleware.ResponderFunc(processInspectResponse(isEncryptOn, k, r))
48+
})
49+
}
50+
51+
func getInspectResult(session *models.Principal, params *admin_api.InspectParams) (*[32]byte, io.ReadCloser, *models.Error) {
52+
ctx := context.Background()
53+
mAdmin, err := NewMinioAdminClient(session)
54+
if err != nil {
55+
return nil, nil, prepareError(err)
56+
}
57+
58+
var cfg madmin.InspectOptions
59+
cfg.File = params.File
60+
cfg.Volume = params.Volume
61+
62+
// create a MinIO Admin Client interface implementation
63+
// defining the client to be used
64+
adminClient := AdminClient{Client: mAdmin}
65+
66+
k, r, err := adminClient.inspect(ctx, cfg)
67+
68+
if err != nil {
69+
return nil, nil, prepareError(err)
70+
}
71+
return &k, r, nil
72+
}
73+
74+
//borrowed from mc cli
75+
func decryptInspect(key [32]byte, r io.Reader) io.ReadCloser {
76+
stream, err := sio.AES_256_GCM.Stream(key[:])
77+
if err != nil {
78+
return nil
79+
}
80+
nonce := make([]byte, stream.NonceSize())
81+
return ioutil.NopCloser(stream.DecryptReader(r, nonce, nil))
82+
}
83+
84+
func processInspectResponse(isEnc bool, k *[32]byte, r io.ReadCloser) func(w http.ResponseWriter, _ runtime.Producer) {
85+
return func(w http.ResponseWriter, _ runtime.Producer) {
86+
var id [4]byte
87+
binary.LittleEndian.PutUint32(id[:], crc32.ChecksumIEEE(k[:]))
88+
defer r.Close()
89+
90+
ext := "enc"
91+
if !isEnc {
92+
ext = "zip"
93+
r = decryptInspect(*k, r)
94+
}
95+
96+
fileName := fmt.Sprintf("inspect.%s.%s", hex.EncodeToString(id[:]), ext)
97+
98+
if isEnc {
99+
// use cookie to transmit the Decryption Key.
100+
hexKey := hex.EncodeToString(id[:]) + hex.EncodeToString(k[:])
101+
cookie := http.Cookie{
102+
Name: fileName,
103+
Value: hexKey,
104+
Path: "/",
105+
MaxAge: 3000,
106+
}
107+
http.SetCookie(w, &cookie)
108+
}
109+
110+
w.Header().Set("Content-Type", "application/octet-stream")
111+
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", fileName))
112+
113+
_, err := io.Copy(w, r)
114+
115+
if err != nil {
116+
LogError("Unable to write all the data: %v", err)
117+
}
118+
}
119+
}

restapi/client-admin.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,11 @@ func (ac AdminClient) addTier(ctx context.Context, cfg *madmin.TierConfig) error
416416
return ac.Client.AddTier(ctx, cfg)
417417
}
418418

419+
// implements madmin.Inspect()
420+
func (ac AdminClient) inspect(ctx context.Context, insOpts madmin.InspectOptions) ([32]byte, io.ReadCloser, error) {
421+
return ac.Client.Inspect(ctx, insOpts)
422+
}
423+
419424
// implements madmin.EditTier()
420425
func (ac AdminClient) editTierCreds(ctx context.Context, tierName string, creds madmin.TierCreds) error {
421426
return ac.Client.EditTier(ctx, tierName, creds)

restapi/configure_console.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ func configureAPI(api *operations.ConsoleAPI) http.Handler {
122122
registerSubnetHandlers(api)
123123
// Register Account handlers
124124
registerAdminTiersHandlers(api)
125+
//Register Inspect Handler
126+
registerInspectHandler(api)
125127

126128
// Operator Console
127129

restapi/embedded_spec.go

Lines changed: 90 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

restapi/operations/admin_api/inspect.go

Lines changed: 88 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)