Open a Micrsoft DFS share in golang using smb2 - go

I have a dfs share on Windows server 2012. I can open the share and read files from another system in a windows file explorer with a path like: \\dfsserver\usernamepace\Tom\go.png. However, using golang's smb2 package by https://github.com/hirochachacha/go-smb2 I get an error as
response error: The contacted server does not support the indicated
part of the DFS namespace
But if I try to open the file with it's actual share path \\dfsserver\public share\Tom\go.png then the code works fine. So the problem is that I have no knowledge of the actual path during runtime and I want to be able to open the file with path provided by DFS.
Could it be the case that DFS does not work properly with smb2? or some other issues. Thanks in advance for your comments.
func main(){
// actualPath := `\\dfsserver\public share\Tom\go.png`
// dfsPath := `\\dfsserver\usernamespace\Tom\go.png`
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%s", "dfsserver", "445"))
if err != nil {
fmt.Println(err)
}
defer conn.Close()
dial := &smb2.Dialer{
Initiator: &smb2.NTLMInitiator{
User: "user",
Password: "password",
Domain: "dfsserver",
},
}
session, err := dial.Dial(conn)
if err != nil {
fmt.Println(err)
}
defer session.Logoff()
mountPoint, err := session.Mount("usernamespace")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// error occures here, if the mountPoint was "public share" instead of "usernamespace" then no error
remoteFile, err := mountPoint.Open(`Tom\go.png`)
defer remoteFile.Close()
if err != nil {
fmt.Println(err)
}
}

Related

Golang windows service not writting to logfile

I have a simple TCP-server written in Go and running as windows service. It installs/uninstalls just fine, it is working as service and doing it's job but it's not writing a single word in a log file. When I run it simply as an executable in a console - logging works fine. But when it starts as a service - log file is created, application process opens it (thus disallowing to delete it for example) but file remains empty. What I'm doing wrong?
Any word of advice is appreciated.
logging is confured like this
func (p *Program) run() {
exec, _ := os.Executable()
WORK_DIR = filepath.Join(filepath.Dir(exec), "ATT")
_, err := checkDir(WORK_DIR)
if err != nil {
panic("Не удалось создать рабочий каталог")
}
f, err := os.OpenFile(filepath.Join(filepath.Dir(exec), "server.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("Не удалось создать лог-файл: %v", err)
}
defer f.Close()
wrt := io.MultiWriter(os.Stdout, f)
log.SetOutput(wrt)
server, err := net.Listen("tcp", ":"+PORT)
if err != nil {
log.Fatal(err)
}
defer server.Close()
log.Println("Сервер запущен на порту:", PORT)
for {
connection, err := server.Accept()
if err != nil {
log.Println("Не удалось установить соединение с клиентом", err)
}
go HandleServer(connection)
}
}
The issue you're encountering with logging can be related to file permissions when running as a service. When a service starts, it runs with a different set of permissions than when it runs as a regular executable. In some cases, the service might not have permission to write to a log file in the same location as the executable.
One possible solution is to specify a different location for the log file, such as C:\Windows\System32\LogFiles, which is a common location for log files in Windows. You could also try specifying the absolute path to the log file in the OpenFile call to avoid any confusion about the working directory.
Another potential issue could be with the defer statement that closes the log file. When the service terminates, any deferred statements will be executed, which could cause the log file to be closed before all log messages have been written. To avoid this, you could remove the defer statement and manually close the log file when the service stops.
It may also be a good idea to add error handling to the logging calls to ensure that all log messages are being written even if the log file becomes unavailable. Here is an example:
func (p *Program) run() {
exec, _ := os.Executable()
WORK_DIR = filepath.Join(filepath.Dir(exec), "ATT")
_, err := checkDir(WORK_DIR)
if err != nil {
panic("Не удалось создать рабочий каталог")
}
// Specify the absolute path for the log file
logFilePath := filepath.Join(filepath.Dir(exec), "server.log")
f, err := os.OpenFile(logFilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("Не удалось создать лог-файл: %v", err)
}
// Remove the defer statement to close the log file manually later
// defer f.Close()
wrt := io.MultiWriter(os.Stdout, f)
log.SetOutput(wrt)
server, err := net.Listen("tcp", ":"+PORT)
if err != nil {
log.Fatal(err)
}
defer server.Close()
log.Println("Сервер запущен на порту:", PORT)
for {
connection, err := server.Accept()
if err != nil {
log.Println("Не удалось установить соединение с клиентом", err)
}
go HandleServer(connection)
}
// Manually close the log file when the service stops
f.Close()
}
// Add error handling to the logging calls
func logMessage(message string) {
_, logErr := log.Println(message)
if logErr != nil {
fmt.Printf("Error logging message: %v\n", logErr)
}
}
I hope these suggestions help you resolve the issue with logging in your service. Please let me know.

Testing NATS-streaming in Kubernetes with minimal effort

I wanted to test a very basic application for NATS-streaming on Kubernetes. To do so, I followed the commands from the official NATS-docs.
It basically comes down to running
kubectl apply -f https://raw.githubusercontent.com/nats-io/k8s/master/nats-server/single-server-nats.yml
kubectl apply -f https://raw.githubusercontent.com/nats-io/k8s/master/nats-streaming-server/single-server-stan.yml
in a terminal with access to the cluster (it's a kind-cluster in my case).
I used stan.go as the NATS-streaming-client. Here is the code I tried to connect to the NATS-streaming-server:
package main
import stan "github.com/nats-io/stan.go"
func main() {
sc, err := stan.Connect("stan", "test-client")
if err != nil {
panic(err)
}
if err := sc.Publish("test-subject", []byte("This is a test-message!")); err != nil {
panic(err)
}
}
and this is the error I'm getting:
panic: nats: no servers available for connection
goroutine 1 [running]:
main.main()
/Users/thilt/tmp/main.go:9 +0x15d
exit status 2
so I think another name was used for the cluster or something. If I use the provided example with nats-box from the docs.nats-link above, it also doesn't work! Where did I go wrong here?
I will happily provide more information, if needed.
There is a great example in stan.go docs:
// Connect to NATS
nc, err := nats.Connect(URL, opts...)
if err != nil {
log.Fatal(err)
}
defer nc.Close()
sc, err := stan.Connect(clusterID, clientID, stan.NatsConn(nc))
if err != nil {
log.Fatalf("Can't connect: %v.\nMake sure a NATS Streaming Server is running at: %s", err, URL)
}
defer sc.Close()
Your error happens because by default stan connects to localhost address (source code):
// DefaultNatsURL is the default URL the client connects to
DefaultNatsURL = "nats://127.0.0.1:4222"
Notice that povided above example overwrite this default connection.
Stan source code is short and easy to analyze. I really recommend you to try to analyze it and figure out what it does.
Now let's put it all together; here is a working example:
package main
import (
nats "github.com/nats-io/nats.go"
stan "github.com/nats-io/stan.go"
)
func main() {
// Create a NATS connection
nc, err := nats.Connect("nats://nats:4222")
if err != nil {
panic(err)
}
// Then pass it to the stan.Connect() call.
sc, err := stan.Connect("stan", "me", stan.NatsConn(nc))
if err != nil {
panic(err)
}
if err := sc.Publish("test-subject", []byte("This is a test-message!")); err != nil {
panic(err)
}
}

Change Permission Bits Google Cloud Functions

I create a function to get data from SQL database using SSL in Go 1.13 and upload these files
So I set the connectionString to:
connString := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s sslmode=verify-ca sslrootcert=%s sslkey=%s sslcert=%s", os.Getenv("HOST"), os.Getenv("PORT1"), os.Getenv("DBNAME"), os.Getenv("USER"), os.Getenv("PASSWORD"), "pathto/server-ca.pem", "pathto/client-cert.pem", "pathto/client-key.pem")
I think the connectionstring is right, but then i got an error like this:
pq: Private key file has group or world access. Permissions should be u=rw (0600) or less
is there a way to modify the permission bits in Cloud Functions file?
You can't achieve this, the files are not mutable. The solution is to copy it in the /tmp directory
f, err := os.Open("pathto/client-key.pem")
if err != nil {
log.Fatal(err)
}
defer f.Close()
d, err := os.Open("/tmp/client-key.pem")
if err != nil {
log.Fatal(err)
}
defer d.Close()
_, err = io.Copy(d, f)
if err != nil {
log.Fatal(err)
}
err = d.Chmod( 0600)
if err != nil {
log.Fatal(err)
}
And then use the /tmp/client-key.pem instead of pathto/client-key.pem

Problem saving file to network folder when receiving the file through lan - Golang

Probably a confusing title.Let me explain
I have a Go server.Users can upload photos.Server takes those photos and saves it to a network folder that points to a static file server.Testing with localhost everything works fine.However when using my phone connected to LAN, .write([]bytes) throws me an error Z:/xxx.jpg: The network connection was aborted by the local system.
I see that it did receive the bytes successfully checking with len([]bytes).Saving to local disk works fine.
I can not find a reason why that would happen.Since the program receives the bytes,how could it differentiate if they came from localhost or through another device?
Here is a snippet from my code
file, _, err := r.FormFile("uploadFile")
defer file.Close()
fileBytes, err := ioutil.ReadAll(file)
filetype := http.DetectContentType(fileBytes)
switch filetype {
case "image/jpeg", "image/jpg":
case "image/gif", "image/png":
case "application/pdf":
break
default:
renderError(w, "INVALID_FILE_TYPE", http.StatusBadRequest)
return
}
fileName := randToken(12)
fileEndings, err := mime.ExtensionsByType(filetype)
if err != nil {
renderError(w, "CANT_READ_FILE_TYPE", http.StatusInternalServerError)
log.Print(err)
return
}
newPath := uploadPath + fileName + fileEndings[0]
newFile, err := os.Create(newPath)
defer newFile.Close()
if _, err := newFile.Write(fileBytes); err != nil || newFile.Close() != nil{
fmt.Println(err)
}
//success

SFTP In Go Error: User does not have appropriate read permission

I am trying to upload a product feed to a Google Merchant SFTP account. I am able to upload a file manually through the command prompt but encounter the following error when trying to do it through Go.
Error: sftp: "User does not have appropriate read permission." (SSH_FX_PERMISSION_DENIED)
I am using the github.com/pkg/sftp package, following the example in https://godoc.org/github.com/pkg/sftp#Client.Open. I suspect that the Create/Write pattern here ends up being different from a simple put from command line.
Code
func (g *GoogleExporter) ExportToSFTP(file []byte) error {
// Creating an SSH connection
sshConfig := &ssh.ClientConfig{
User: g.Creds.AccessData.SFTPUser,
Auth: []ssh.AuthMethod{
ssh.Password(g.Creds.AccessData.SFTPPassword),
},
}
hostPort := fmt.Sprintf("%s:%d", SFTPHostName, SFTPHostPort)
connection, err := ssh.Dial("tcp", hostPort, sshConfig)
if err != nil {
return err
}
fmt.Println(">> SSH Connection Created!")
// Creating an SFPT connection over SSH
sftp, err := sftp.NewClient(connection)
if err != nil {
return err
}
defer sftp.Close()
fmt.Println(">> SFTP Client Created!")
// Uploading the file
remoteFileName := "products.xml" // TODO: Make this name configurable
remoteFile, err := sftp.Create(remoteFileName)
if err != nil {
return err
}
fmt.Println(">> SFTP File Created!")
if _, err := remoteFile.Write(file); err != nil {
return err
}
fmt.Println("Successfully uploaded product feed to SFTP, file:%s user:%s", remoteFileName, g.Creds.AccessData.SFTPUser)
util.Log("Successfully uploaded product feed to SFTP, file:%s user:%s", remoteFileName, g.Creds.AccessData.SFTPUser)
// Confirming if the file is there
if _, err := sftp.Lstat(remoteFileName); err != nil {
return err
}
return nil
}
The error is cause by this line:
remoteFile, err := sftp.Create(remoteFileName)
I am answering my own question to help anyone else that is having this problem. I was able to find a solution.
The Google Merchant SFTP account only gives you write only access. However, according to the docs, when using the sftp.Create(..) function, it creates a file with the flags as 0666, which does not agree with the permissions set on your user.
To mimic the behavior of sftp.Create(..) with write only permissions, you can use the more general sftp.OpenFile(..) function.
remoteFile, err := sftp.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
The flags os.O_WRONLY|os.O_CREATE|os.O_TRUNC will mimic the behavior of Create() i.e. create a file it doesn't exist and truncate the file if it does.

Resources