Gerenciar permissão de acesso pode ser uma grande dor de cabeça. Verificar se o usuário precisa estar logado, se tem acesso aquele recurso ou funcionalidade, se o link acessado ainda é válido, dentre outras coisas.
Atualmente quando falamos de permissão de acesso a arquivos em buckets, alguns cloud providers oferecem um recurso conhecido como URLs assinadas (Signed URL). Tal recurso nos permite configurar um controle de acesso temporário a arquivos dentro de buckets privados.
Nesse post, vou mostrar como fazer upload de um arquivo para um bucket privado e gerar uma URL assinada para acesso temporário.
Upload do arquivo
Para fazer o upload, assumo que você já tenha um bucket privado criado no Google Cloud Storage (GCS) e que sua aplicação já tenha acesso a ele.
A função, como podemos ver abaixo, terá os parâmetros:
bucket: nome do bucket do GCS;object: nome do objeto no GCS (normalmente o nome do arquivo e o caminho onde ele ficará no bucket);file: um ponteiro do arquivo que será feito upload.
import (
"context"
"io"
"os"
"cloud.google.com/go/storage"
)
func uploadFile(bucket, object string, file *os.File) error {
ctx := context.Background()
// inicia um novo client com o GCS
client, err := storage.NewClient(ctx)
if err != nil {
return err
}
defer client.Close()
// cria um novo writer para receber o arquivo que será feito upload
wc := client.Bucket(bucket).Object(object).NewWriter(ctx)
// copia o arquivo para o writer criado acima
if _, err = io.Copy(wc, file); err != nil {
return err
}
if err := wc.Close(); err != nil {
return err
}
return nil
}
A decisão por passar o arquivo como um ponteiro de os.File ao invés do caminho de onde o arquivo está, garante com que essa função possa ser utilizada de diferentes formas, como por exemplo:
- O objeto retornado da leitura de um arquivo local com
os.Open; - O arquivo recebido via API, sem a necessidade de ter que criá-lo localmente;
- O arquivo lido de outro bucket…
URL assinada
Agora que temos o arquivo no bucket privado, para dar acesso temporário à ele, vamos implementar a função que irá gerar a URL assinada.
func generateSignedURL(bucket, object string, expires time.Duration) (string, error) {
ctx := context.Background()
// inicia um novo client com o GCS
client, err := storage.NewClient(ctx)
if err != nil {
return "", err
}
defer client.Close()
opts := &storage.SignedURLOptions{
Method: "GET",
Expires: time.Now().Add(expires),
}
// gera a URL assinada
url, err := client.Bucket(bucket).SignedURL(object, opts)
if err != nil {
return "", err
}
return url, nil
}
Note que um dos atributos do objeto storage.SignedURLOptions é o método HTTP que aquela URL terá permissão. No exemplo, utilizamos GET, pois queremos dar acesso ao arquivo que já foi enviado para o bucket.
Caso você queria fornecer uma URL assinada para que um terceiro faça upload diretamente para seu bucket privado, tudo que precisa fazer é mudar o método GET para PUT.
Com essa mudança, a URL gerada dará permissão para que um terceiro faça upload para o caminho definido no parâmetro object.
Conclusão
Usando o package do Google Cloud para Go, você pode facilmente carregar arquivos para o GCS e gerar URLs assinadas para compartilhá-los de forma segura, além de poder gerar URLs para que outros sistemas façam upload de forma segura para seu bucket privado.
No próximo post sobre Google Cloud, vou mostrar algumas formas de autenticação, assim como seus prós e contras.
Até a próxima.
Faça parte da comunidade!
Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.
Livros Recomendados
Abaixo listei alguns dos melhores livros que já li sobre GO.




