Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Инкремент №22 #20

Merged
merged 3 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
*.out.tmp

# Binaries
cmd/agent/main
Expand All @@ -25,3 +26,5 @@ vendor/
.vscode

.DS_Store

*.prof
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,12 @@ git fetch template && git checkout template/main .github
При мёрже ветки с инкрементом в основную ветку `main` будут запускаться все автотесты.

Подробнее про локальный и автоматический запуск читайте в [README автотестов](https://github.com/Yandex-Practicum/go-autotests).




openssl genpkey -algorithm RSA -out example_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -in example_key.pem -pubout -out example_key.pub.pem


go run cmd/server/main.go --crypto-key=/Users/ex0rcist/projects/go/yp/metflix/key_example
6 changes: 6 additions & 0 deletions config/agent.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"address": "localhost:8080",
"report_interval": 3,
"poll_interval": 1,
"crypto_key": "./example_key.pub.pem"
}
8 changes: 8 additions & 0 deletions config/server.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"address": "localhost:8080",
"restore": true,
"store_interval": 1,
"store_file": "./metflix.db",

"crypto_key": "./example_key.pem"
}
835 changes: 0 additions & 835 deletions coverage.out.tmp

This file was deleted.

28 changes: 28 additions & 0 deletions example_key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDAc/6Js4iWRfLp
I/7cshsxxxU9cYeGZubuW+wmt/NjRJaSRU/NvJ3h8tYAOWmn/U7umEBcDtoXC2zl
cInj867KklrouXmlwiWhvomLTUJh/jg+jtuUbmhJckuzHwzXJoDqBbGP359g/uUu
qsr870xqTaNGFN224t39M+3PDOWX6jkkbztIOwXBoP4Z49j6JphbZRUAW6Q/jgvP
q1OjfDM/7qoBlD5Y7o0/gafo8wVTQjhBcR6ueSyQmRE760xZ6BguJhaAdXz7pw58
DTzxWLxM6pRJfN+fslRr5FPh4DBIE6Ck+GIG+4Jqt10++r133mKO3eSOnuRPQOUT
Vs40K3IJAgMBAAECggEABUbo8tOmaiBu4a+n/Fsx3bKMxYuIYMoPiPeiSQmANfea
fVZDMuv6FEj5TzZDzGRotqgcE6oglsMscDoevc5fu5Q5w+naCQ6Cw6Wa1eP/bvpu
hmCaar6AQ4tLwhSW4Itgu4n+bWh/UUSL+jSarkbNfJi2YmSOE8ayuY+j9Kpw3TJ1
rAQ/TVJSBTsL7uP76928OReP4azoOZabQiejMNunNSpFy3Ds36Dy2eGpyLZFL7+s
jmog+Q4PYiho9fJB1XJb3sCop9Vb6vNJ6h2ji0cNzhz2q84DHxav7hQEwGGaaHeR
0WotC+Hiy6YNZxHwbLu7EuhKfhgbx/E4rbt+8yyiEQKBgQD7lAxvEJtVer50lqTZ
FbKBR903GVmRDCXlqlIXrNWXGHhHL/qrQSqeJhLLTkkfcA22nxFTAWEKUeG+MGLW
njp4RAUKNxi4EBvPlH+iKbq3bOpJrtfPb/2rjJ4I9+4B85n41dAgybbMzo9U/cNY
xMVhFTz5ZSV+w1ZnzGjXDFQDlQKBgQDD1erxmmbw4AT9Mukfii7XkFsjY4xGamuX
AgiNhbPZcAxm2TCt8FRR2RxIZIVxWlI8q9JHKZlsuGf1HQZIeR9DKE8BGsam9aEP
sVby1OxcLdErAtPxZpR2DCgdjgJPFfBIpfy9K8FoUhlaAlfNvTCueQG78/dZSawA
6pdAtjfXpQKBgQDOtR5iQ2reGTRT51Mba1B4GOwSUaneG/Und4JsIX5934U0OJ/m
Bm1V9EKM+Y3rXs5ltt0tLnzlVdH9yxPq86dnGbxqYErXMaUoMgOM4mygOcVnNVns
/z+WrLtM8ymEQPvKESQpTJP+Q9pRIxBW55al5iVrZUghl65vKu0ZhO+i4QKBgHQ4
yjwkdB9T8+IIis3LBk2sQEpaU++eTMfLzyOeS8QpeVK4ZulzjbcdcGmOLpu9DL0x
A5R0HbemIRwY45ezOlhy3aA8MdT4RWO4zW9D6hoynsY14W6MgGMmh9AybTBeRsH2
sG3cP+YXgzAl39IcC34gFmVjPlJhJJFOqAEhozZ5AoGBAIjlG3DQfmisZ9ODIRJw
8sEfNy+BggsQpDeV4XR2s10wFnfs8YBOpe3hltwBWnC3MHxvJ95hhtXDZALQc8AS
8jzyzWUQUIwlqragywvEr5nl3zALw8OYLfy5UhbHpBg4nuwilKgsBVR+kOlwOPro
UdDRvssb7IK2GY83KTzBBKwg
-----END PRIVATE KEY-----
9 changes: 9 additions & 0 deletions example_key.pub.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwHP+ibOIlkXy6SP+3LIb
MccVPXGHhmbm7lvsJrfzY0SWkkVPzbyd4fLWADlpp/1O7phAXA7aFwts5XCJ4/Ou
ypJa6Ll5pcIlob6Ji01CYf44Po7blG5oSXJLsx8M1yaA6gWxj9+fYP7lLqrK/O9M
ak2jRhTdtuLd/TPtzwzll+o5JG87SDsFwaD+GePY+iaYW2UVAFukP44Lz6tTo3wz
P+6qAZQ+WO6NP4Gn6PMFU0I4QXEernkskJkRO+tMWegYLiYWgHV8+6cOfA088Vi8
TOqUSXzfn7JUa+RT4eAwSBOgpPhiBvuCarddPvq9d95ijt3kjp7kT0DlE1bONCty
CQIDAQAB
-----END PUBLIC KEY-----
94 changes: 78 additions & 16 deletions internal/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package agent

import (
"context"
"encoding/json"
"fmt"
"os"
"strings"
"sync"
"time"
Expand All @@ -11,7 +13,7 @@ import (
"github.com/ex0rcist/metflix/internal/agent/exporter"
"github.com/ex0rcist/metflix/internal/entities"
"github.com/ex0rcist/metflix/internal/logging"
"github.com/ex0rcist/metflix/internal/services"
"github.com/ex0rcist/metflix/internal/security"
"github.com/ex0rcist/metflix/internal/utils"
"github.com/spf13/pflag"
)
Expand All @@ -22,16 +24,19 @@ type Agent struct {
Stats *Stats
Exporter exporter.Exporter

publicKey security.PublicKey

wg sync.WaitGroup
}

// Agent config.
type Config struct {
Address entities.Address `env:"ADDRESS"`
PollInterval int `env:"POLL_INTERVAL"`
ReportInterval int `env:"REPORT_INTERVAL"`
RateLimit int `env:"RATE_LIMIT"`
Secret entities.Secret `env:"KEY"`
Address entities.Address `env:"ADDRESS" json:"address"`
PollInterval int `env:"POLL_INTERVAL" json:"poll_interval"`
ReportInterval int `env:"REPORT_INTERVAL" json:"report_interval"`
RateLimit int `env:"RATE_LIMIT" json:"-"`
Secret entities.Secret `env:"KEY" json:"key"`
PublicKeyPath entities.FilePath `env:"CRYPTO_KEY" json:"crypto_key"`
}

// Constructor.
Expand All @@ -48,15 +53,24 @@ func New() (*Agent, error) {
return nil, err
}

exporter, err := newMetricsExporter(config)
var key security.PublicKey
if len(config.PublicKeyPath) != 0 {
key, err = security.NewPublicKey(config.PublicKeyPath)
if err != nil {
return nil, err
}
}

exporter, err := newMetricsExporter(config, key)
if err != nil {
return nil, err
}

return &Agent{
Config: config,
Stats: NewStats(),
Exporter: exporter,
Config: config,
Stats: NewStats(),
Exporter: exporter,
publicKey: key,
}, nil
}

Expand Down Expand Up @@ -171,6 +185,10 @@ func (c Config) String() string {
str = append(str, fmt.Sprintf("secret=%v", c.Secret))
}

if len(c.PublicKeyPath) > 0 {
str = append(str, fmt.Sprintf("public-key=%v", c.PublicKeyPath))
}

return "agent config: " + strings.Join(str, "; ")
}

Expand All @@ -187,22 +205,22 @@ func detectExporterKind(c *Config) string {
return ek
}

func newMetricsExporter(config *Config) (exporter.Exporter, error) {
func newMetricsExporter(config *Config, publicKey security.PublicKey) (exporter.Exporter, error) {
var exp exporter.Exporter
var signer services.Signer
var signer security.Signer
var err error

if len(config.Secret) > 0 {
signer = services.NewSignerService(config.Secret)
signer = security.NewSignerService(config.Secret)
}

exporterKind := detectExporterKind(config)

switch exporterKind {
case exporter.KindLimited:
exp = exporter.NewLimitedExporter(&config.Address, signer, config.RateLimit)
exp = exporter.NewLimitedExporter(&config.Address, signer, config.RateLimit, publicKey)
case exporter.KindBatch:
exp = exporter.NewBatchExporter(&config.Address, signer)
exp = exporter.NewBatchExporter(&config.Address, signer, publicKey)
default:
exp, err = nil, fmt.Errorf("unknown exporter type")
}
Expand All @@ -211,25 +229,37 @@ func newMetricsExporter(config *Config) (exporter.Exporter, error) {
}

func parseConfig(config *Config) error {
err := tryLoadJSONConfig(config)
if err != nil {
return err
}

address := config.Address
pflag.VarP(&address, "address", "a", "address:port for HTTP API requests")

secret := config.Secret
pflag.VarP(&secret, "secret", "k", "a key to sign outgoing data")

publicKeyPath := config.PublicKeyPath
pflag.VarP(&publicKeyPath, "crypto-key", "", "path to public key to encrypt agent -> server communications")

configPath := entities.FilePath("") // register var for compatibility
pflag.VarP(&configPath, "config", "c", "path to configuration file in JSON format")

pflag.IntVarP(&config.PollInterval, "poll-interval", "p", config.PollInterval, "interval (s) for polling stats")
pflag.IntVarP(&config.ReportInterval, "report-interval", "r", config.ReportInterval, "interval (s) for polling stats")
pflag.IntVarP(&config.RateLimit, "rate-limit", "l", config.RateLimit, "number of max simultaneous requests to server")

pflag.Parse()

// because VarP gets non-pointer value, set it manually
pflag.Visit(func(f *pflag.Flag) {
switch f.Name {
case "address":
config.Address = address
case "secret":
config.Secret = secret
case "crypto-key":
config.PublicKeyPath = publicKeyPath
}
})

Expand All @@ -239,3 +269,35 @@ func parseConfig(config *Config) error {

return nil
}

func tryLoadJSONConfig(dst *Config) error {
var configArg string
for i, arg := range os.Args {
if (arg == "-c" || arg == "--config") && i+1 < len(os.Args) {
configArg = os.Args[i+1]
break
}
}

if len(configArg) > 0 {
err := loadConfigFromFile(entities.FilePath(configArg), dst)
if err != nil {
return err
}
}

return nil
}

func loadConfigFromFile(src entities.FilePath, dst *Config) error {
data, err := os.ReadFile(src.String())
if err != nil {
return fmt.Errorf("agent.loadConfigFromFile - os.ReadFile: %w", err)
}

if err := json.Unmarshal(data, dst); err != nil {
return fmt.Errorf("agent.loadConfigFromFile - json.Unmarshal: %w", err)
}

return nil
}
25 changes: 17 additions & 8 deletions internal/agent/exporter/batch_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/ex0rcist/metflix/internal/entities"
"github.com/ex0rcist/metflix/internal/logging"
"github.com/ex0rcist/metflix/internal/retrier"
"github.com/ex0rcist/metflix/internal/services"
"github.com/ex0rcist/metflix/internal/security"
"github.com/ex0rcist/metflix/internal/utils"
"github.com/ex0rcist/metflix/pkg/metrics"
)
Expand All @@ -21,24 +21,26 @@ var _ Exporter = (*BatchExporter)(nil)

// Batch exporter to optimize requests count.
type BatchExporter struct {
baseURL *entities.Address
client *http.Client
signer services.Signer
baseURL *entities.Address
client *http.Client
signer security.Signer
publicKey security.PublicKey

buffer []metrics.MetricExchange
err error
}

// Constructor.
func NewBatchExporter(baseURL *entities.Address, signer services.Signer) *BatchExporter {
func NewBatchExporter(baseURL *entities.Address, signer security.Signer, publicKey security.PublicKey) *BatchExporter {
client := &http.Client{
Timeout: 2 * time.Second,
}

return &BatchExporter{
baseURL: baseURL,
client: client,
signer: signer,
baseURL: baseURL,
client: client,
signer: signer,
publicKey: publicKey,
}
}

Expand Down Expand Up @@ -123,6 +125,13 @@ func (e *BatchExporter) doSend() error {
return err
}

if e.publicKey != nil {
payload, err = security.Encrypt(io.Reader(payload), e.publicKey)
if err != nil {
return err
}
}

url := "http://" + e.baseURL.String() + "/updates"
req, err := http.NewRequest(http.MethodPost, url, payload)
if err != nil {
Expand Down
Loading
Loading