Skip to content

Commit

Permalink
[JENKINS-73305] Create .ssh directory with owner only permissions
Browse files Browse the repository at this point in the history
When the JGit implementation needs to create a `.ssh` directory, create
it with permissions only allowing access to the directory owner.  That is
the common pattern used by the OpenSSH project and by POSIX systems to
reduce access to the sensitive information stored in the directory.

Testing done

Ran the CredentialsTest in a debugger with a configured 'auth-data`
directory and confirmed that the modified lines are executed on my
RHEL 8 development computer.  Confirmed that the resulting directory
permissions were read, write, and execute for only the owner, with no
other permissions.
  • Loading branch information
MarkEWaite committed Jun 16, 2024
1 parent f988d25 commit a09e86f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 11 deletions.
28 changes: 24 additions & 4 deletions src/main/java/org/jenkinsci/plugins/gitclient/JGitAPIImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -201,10 +204,22 @@ public class JGitAPIImpl extends LegacyCompatibleGitAPIImpl {
public SshdSessionFactory buildSshdSessionFactory(@NonNull final HostKeyVerifierFactory hostKeyVerifierFactory) {
if (Files.notExists(hostKeyVerifierFactory.getKnownHostsFile().toPath())) {
try {
Files.createDirectories(hostKeyVerifierFactory
.getKnownHostsFile()
.getParentFile()
.toPath());
if (isWindows()) {

Check warning on line 207 in src/main/java/org/jenkinsci/plugins/gitclient/JGitAPIImpl.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 207 is only partially covered, one branch is missing
Files.createDirectories(hostKeyVerifierFactory
.getKnownHostsFile()
.getParentFile()
.toPath());
} else {
Set<PosixFilePermission> ownerOnly = PosixFilePermissions.fromString("rwx------");
FileAttribute<Set<PosixFilePermission>> fileAttribute =
PosixFilePermissions.asFileAttribute(ownerOnly);
Files.createDirectories(
hostKeyVerifierFactory
.getKnownHostsFile()
.getParentFile()
.toPath(),
fileAttribute);
}
Files.createFile(hostKeyVerifierFactory.getKnownHostsFile().toPath());
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "could not create known hosts file", e);
Expand Down Expand Up @@ -3231,4 +3246,9 @@ public void close() {
}
}
}

/** inline ${@link hudson.Functions#isWindows()} to prevent a transient remote classloader issue */
private static boolean isWindows() {
return File.pathSeparatorChar == ';';

Check warning on line 3252 in src/main/java/org/jenkinsci/plugins/gitclient/JGitAPIImpl.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 3252 is only partially covered, one branch is missing
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.jgit.transport.sshd.ServerKeyDatabase;
Expand All @@ -29,19 +33,28 @@ public AbstractCliGitHostKeyVerifier forCliGit(TaskListener listener) {
};
}

private void createKnownHostsFile(Path knowHostPath) throws IOException {
Path parent = knowHostPath.getParent();
if (parent == null) {
throw new IllegalArgumentException("knowHostPath parent cannot be null");
}
if (isWindows()) {
Files.createDirectories(parent);
} else {
Set<PosixFilePermission> ownerOnly = PosixFilePermissions.fromString("rwx------");
FileAttribute<Set<PosixFilePermission>> fileAttribute = PosixFilePermissions.asFileAttribute(ownerOnly);
Files.createDirectories(parent, fileAttribute);
}
Files.createFile(knowHostPath);
}

@Override
public AbstractJGitHostKeyVerifier forJGit(TaskListener listener) {
Path knowHostPath = getKnownHostsFile().toPath();
if (Files.notExists(knowHostPath)) {
try {
logHint(listener);
Path parent = knowHostPath.getParent();
if (parent != null) {
Files.createDirectories(parent);
Files.createFile(knowHostPath);
} else {
throw new IllegalArgumentException("knowHostPath parent cannot be null");
}
createKnownHostsFile(knowHostPath);
} catch (IOException e) {
LOGGER.log(Level.WARNING, e, () -> "Could not load known hosts.");
}
Expand Down Expand Up @@ -76,4 +89,9 @@ private void logHint(TaskListener listener) {
"Known hosts file {0} not found, but verifying host keys with known hosts file",
new Object[] {SshHostKeyVerificationStrategy.KNOWN_HOSTS_DEFAULT});
}

/** inline ${@link hudson.Functions#isWindows()} to prevent a transient remote classloader issue */
private static boolean isWindows() {
return File.pathSeparatorChar == ';';

Check warning on line 95 in src/main/java/org/jenkinsci/plugins/gitclient/verifier/KnownHostsFileVerifier.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 37-95 are not covered by tests
}
}

0 comments on commit a09e86f

Please sign in to comment.