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

Safe logging #47

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open

Safe logging #47

wants to merge 7 commits into from

Conversation

jeffdyke
Copy link

@jeffdyke jeffdyke commented Aug 8, 2019

This PR changes how commands are logged and its completely opt-in, defaulting to the normal behaviour promiscuous logging. It also adds the actual exception message to the log for easier debugging. I'm completely open to suggestions.

.gitignore Outdated
project/plugins/target
.idea
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should rather go into your dev machine's global .gitignore, not this project-level file.
(The comment at the top of this file has more details...)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

@@ -18,11 +18,26 @@ package com.decodified.scalassh

import java.io.{ByteArrayInputStream, File, FileInputStream, InputStream}
import net.schmizz.sshj.connection.channel.direct.Session

final case class Command(command: String, input: CommandInput = CommandInput.NoInput, timeout: Option[Int] = None)
trait Command {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this a sealed trait.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this was reverted, perhaps i should be a different PR.


final case class Command(command: String, input: CommandInput = CommandInput.NoInput, timeout: Option[Int] = None)
trait Command {
val command: String
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All those vals should be defs.
Usually abstract members are defined as defs in Scala since this leaves the decision of how to implement the member to the "implementee", without any drawbacks.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct, but these are not longer here.

val command: String
val input: CommandInput = CommandInput.NoInput
val timeout: Option[Int] = None
val safe: Boolean
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say that "safe" in the context of a Command would usually be understood as sth like "safe to run", as in "doesn't do any harm".
What we are looking for here is sth more like "safe to be logged in the clear".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was quite ambiguous, the new value that can be passed into Command is safeToLog and is still opt in.

override val timeout: Option[Int] = None,
safe: Boolean = true)
extends Command
case class UnsafeCommand(command: String,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two sub-types of the ADT here are structually identical, so there appears to be little value of refactoring to an ADT in the first place.
Also, what would SafeCommand(..., safe = false) or UnsafeCommand(..., safe = true) signify?

It seems we can accomplish everything you want to do by simply adding one boolean flag to the existing Command case class, no?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all gone...

@@ -53,9 +52,10 @@ final class SshClient(val config: HostConfig) extends ScpTransferable {
execWithSession(command, session)
}
}
def logCmd(command: Command): String = if (command.safe) command.command else "Sensitive data, not logged"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to me as a bit coarse-grained.

What we want to achieve is not to log sensitive data, which are usually arguments to commands rather than the commands themselves.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also gone, at first i thought i would need it in more than on place, but not the case.

@sirthias
Copy link
Owner

Thank you, @jeffdyke, for this proposal.
I have the feeling, however, that this is not yet the best approach to solve the problem of "having a way to prevent sensitive data from being logged".

How about giving commands the ability to control their own logging?
The default could be a simple .toString (what we currently have) and sensitive commands could construct their own logging output in any way they seem fit, which would usually be a "redacted" .toString or sth like that?

@jeffdyke
Copy link
Author

@sirthias thanks for your input. I'll give this some more time on your comments and clean it up. Looking at your comments i did make it a bit more verbose than i needed, so your view is appreciated.

Copy link
Author

@jeffdyke jeffdyke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @sirthias, i've gone with a much simpler approach, not sure why i was so verbose in the first place. I could open up a new PR against master if this becomes to messy.

.gitignore Outdated
project/plugins/target
.idea
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

@@ -18,11 +18,26 @@ package com.decodified.scalassh

import java.io.{ByteArrayInputStream, File, FileInputStream, InputStream}
import net.schmizz.sshj.connection.channel.direct.Session

final case class Command(command: String, input: CommandInput = CommandInput.NoInput, timeout: Option[Int] = None)
trait Command {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this was reverted, perhaps i should be a different PR.


final case class Command(command: String, input: CommandInput = CommandInput.NoInput, timeout: Option[Int] = None)
trait Command {
val command: String
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct, but these are not longer here.

val command: String
val input: CommandInput = CommandInput.NoInput
val timeout: Option[Int] = None
val safe: Boolean
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was quite ambiguous, the new value that can be passed into Command is safeToLog and is still opt in.

override val timeout: Option[Int] = None,
safe: Boolean = true)
extends Command
case class UnsafeCommand(command: String,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all gone...

@@ -53,9 +52,10 @@ final class SshClient(val config: HostConfig) extends ScpTransferable {
execWithSession(command, session)
}
}
def logCmd(command: Command): String = if (command.safe) command.command else "Sensitive data, not logged"
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also gone, at first i thought i would need it in more than on place, but not the case.

@jeffdyke
Copy link
Author

While the comments are meaningfull, they are worthless...you'd likely rather re-review the full diff, i made it much simpler, looking forward to your thoughts, no breaking changes still. Thanks @sirthias!


object Command {
implicit def fromString(cmd: String): Command = Command(cmd)
def apply(cmd: String, safeToLog: Boolean): Command = new Command(cmd, safeToLog = safeToLog)
def apply(cmd: String): Command = new Command(cmd, safeToLog = true)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more for people looking at the change, it can removed, there is no need to supply safeToLog here. Obviously this can also just be added to the readme.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants